home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / mc302emb.zip / CINTRO.DOC < prev    next >
Text File  |  1994-03-18  |  119KB  |  2,534 lines

  1.    
  2.    
  3.    
  4.    
  5.    
  6.    
  7.    
  8.    
  9.    
  10.    
  11.    
  12.    
  13.                                       An
  14.                                  Introduction
  15.                                       to
  16.    
  17.    
  18.                                      CCC
  19.                                     CC CC
  20.                                    CC   CC
  21.                                    CC
  22.                                    CC   CC
  23.                                     CC CC
  24.                                      CCC
  25.    
  26.    
  27.                                     Using
  28.                            The DDS MICRO-C Compiler
  29.    
  30.    
  31.    
  32.    
  33.    
  34.    
  35.    
  36.    
  37.    
  38.    
  39.                               Revised: 03-Jan-94
  40.    
  41.    
  42.    
  43.    
  44.    
  45.    
  46.    
  47.    
  48.    
  49.    
  50.                       Copyright 1989-1994 Dave Dunfield
  51.                              All rights reserved
  52.    Intro to DDS MICRO-C                                             Page: 1
  53.  
  54.  
  55.    1. INTRODUCTION
  56.    
  57.          Since releasing my MICRO-C compiler in 1988, I have received  many
  58.       requests to include information on the 'C' language as part  of  that
  59.       package.
  60.    
  61.          This manual is intended as a companion to  the  MICRO-C  compiler,
  62.       and presents an introduction to the 'C' language for  those  who  are
  63.       not already familiar  with  it.  The  language  represented  is  that
  64.       portion of 'C' which is implemented by the  MICRO-C  compiler.  Since
  65.       MICRO-C implements a  subset  of  the  'C'  programming  language  as
  66.       described by Kernighan and Ritchie (the original  developers  of  the
  67.       language), you should have little difficulty  using  and  learning  a
  68.       full 'C' compiler once you have mastered it.
  69.    
  70.          You should also refer to the  MICRO-C  technical  manual  entitled
  71.       "MICRO-C a compact 'C' compiler for small systems" for details on the
  72.       MICRO-C implementation.
  73.    
  74.          'C' has many inter-relationships between  its  various  constructs
  75.       and features. I have attempted to introduce them  in  a  logical  and
  76.       "building" manner,  however  it  is  not  always  possible  to  fully
  77.       describe each feature before it is mentioned in  the  description  of
  78.       some other construct. For this reason, I suggest that you  read  this
  79.       text "lightly from cover to cover" at least once before  you  try  to
  80.       fully understand each point.
  81.    
  82.          This is a first draft of this document. In its present form, it is
  83.       not very easy reading, but does contain much  useful  information.  I
  84.       will be improving and adding to it as I find the time.
  85.    
  86.          Presented herein is a brief summary of the major features  of  the
  87.       'C' language as implemented in MICRO-C.
  88.    
  89.          NOTE: If you are using  a  version  of  MICRO-C  for  an  embedded
  90.       processor, some of the library functions and  features  described  in
  91.       this document may be  different  or  unavailable.  For  example,  the
  92.       "file" functions do not exist for any system which does not  have  an
  93.       operating system or disk drives.
  94.    Intro to DDS MICRO-C                                             Page: 2
  95.  
  96.  
  97.    2. BACKGROUND INFORMATION
  98.    
  99.          This section provides some detailed background information for the
  100.       novice, and may be skipped if  you  are  already  familier  with  the
  101.       basics of  computer  architecture  and  programming  languages.  This
  102.       information is presented  here  because  'C'  is  a  very  low  level
  103.       language, and an understanding of these basic  principals  will  help
  104.       you more easily understand how and why certain  constructs  work  the
  105.       way they do.
  106.    
  107.          If you really  don't  want  to  be  bothered  with  learning  "How
  108.       Computers Work", and just want to be able to write simple programs in
  109.       'C',  you  may  skip  this  section   and   proceed   directly   with
  110.       "Introduction To 'C'".
  111.    
  112.       2.1 Computer Architecture
  113.    
  114.             The basis of any computer system is its Central Processor  Unit
  115.          (CPU) which controls the operation  of  all  other  parts  of  the
  116.          computer, by following a set of "instructions"  which  make  up  a
  117.          software "program". The program is stored in "memory" and  directs
  118.          the CPU to read and write data  to  various  "peripheral"  devices
  119.          (Such as terminals, disks and printers), and  to  manipulate  that
  120.          data in a matter which accomplishes  the  goals  set  out  by  the
  121.          author of the program.
  122.    
  123.             Although there are a wide variety of CPUs available  in  modern
  124.          computers, they are all very similar, and  feature  the  following
  125.          characteristics:
  126.    
  127.             All data accessed by the CPU is represented by  circuits  which
  128.          may be either OFF or ON. This is represented by the digits  0  and
  129.          1. Since there are only two states (0 and 1), the computer may  be
  130.          thought of as operating in a BASE 2 (Binary)  number  system,  and
  131.          each individual data element is called a  Binary  digIT,  or  BIT.
  132.          This BASE 2 number system is used because it  is  much  easier  to
  133.          build and interface to electrical circuits  which  have  only  two
  134.          states (OFF and ON) than ones which have many states.
  135.    
  136.             Since  single   BITs   cannot   represent   much   information,
  137.          manipulating large amounts of data at the BIT  level  would  be  a
  138.          very tedious chore. For this reason, modern CPUs  access  data  as
  139.          groups of BITs. Usually the smallest group of data  which  can  be
  140.          manipulated by a computer consists of 8  BITs,  and  is  called  a
  141.          BinarY TErm (BYTE).
  142.    Intro to DDS MICRO-C                                             Page: 3
  143.  
  144.  
  145.             Very small computers can often only access data a BYTE (8 bits)
  146.          at a time, while  larger  machines  may  be  able  to  access  and
  147.          manipulate data in larger groups called WORDS.  The  size  of  the
  148.          data group usually manipulated by a CPU is  called  its  WORDSIZE,
  149.          and is expressed in a number of bits.  This  is  almost  always  a
  150.          multiple of 8 bits, resulting in an even number of bytes. Thus, if
  151.          you hear a CPU or computer called a "16  bit"  machine,  you  know
  152.          that it can access and manipulate 16 bits (2 bytes) of data  at  a
  153.          time. A "32 bit" machine would operate on 32  bits  (4  bytes)  of
  154.          data. In general, the larger the WORDSIZE of a CPU, the more  data
  155.          it manipulates at one time, resulting in faster  completion  of  a
  156.          given task.
  157.    
  158.             The CPU has access to external "memory", which consists of many
  159.          thousands (and often  millions)  of  WORDS  of  data.  Up  to  one
  160.          complete word of data may  be  transferred  between  the  CPU  and
  161.          memory in one memory access.
  162.    
  163.             Often it is known that each data element stored in memory  will
  164.          not take up an entire word, and is it desirable to  access  memory
  165.          in smaller groups, to reduce the number of memory  words  required
  166.          to accomplish a particular task. For this reason, most modern CPUs
  167.          can access any single BYTE (8 bits) from a memory word. It  should
  168.          be understood however, that accessing a single byte causes a  full
  169.          memory access, and takes just as much time as accessing an  entire
  170.          word.
  171.    
  172.             In order to provide the programmer  with  a  simple  method  of
  173.          specifying memory locations, each BYTE of memory  is  assigned  an
  174.          ADDRESS, which is simply the number of BYTES from the beginning of
  175.          memory to the desired byte. Therefore, the first  byte  in  memory
  176.          has address 0, the second byte byte in memory has address  1,  the
  177.          third byte has address 2 etc. Thus, memory from the  viewpoint  of
  178.          the programmer may be considered  as  a  simple  array  of  BYTES,
  179.          beginning with an address of 0,  and  continuing  with  sequential
  180.          addresses up the memory size (in bytes) of the computer.
  181.    
  182.             In addition to the external memory, a CPU has a small amount of
  183.          very fast internal memory which is  organized  into  words  called
  184.          "registers". Registers act as holding places  to  store  the  data
  185.          words which are to be manipulated. At least some of the  registers
  186.          are internally connected to an Arithmetic Logic Unit (ALU),  which
  187.          has the necessary electronics to perform basic operations such  as
  188.          addition and subtraction on  the  data  in  those  registers.  The
  189.          result of the operation is also placed in a register, often one of
  190.          the registers which contained the original data.
  191.    Intro to DDS MICRO-C                                             Page: 4
  192.  
  193.  
  194.             One special register called the Program Counter (PC) is used by
  195.          the CPU to follow the software program. It contains the address of
  196.          the next INSTRUCTION to  be  executed.  At  the  beginning  of  an
  197.          INSTRUCTION CYCLE, the CPU reads the word of memory at the address
  198.          which is contained in the PC, and interprets the  value  contained
  199.          there as an operation to be performed, such as loading a  register
  200.          from memory, storing a register  into  memory,  or  performing  an
  201.          arithmetic operation  on  the  registers.  After  performing  that
  202.          operation, the CPU advances the PC to the next memory word  before
  203.          beginning another instruction cycle. In this manner,  all  of  the
  204.          instructions in a program are read, and the programmed  operations
  205.          are carried out.
  206.    
  207.             The CPU may also read from and  increment  the  PC  during  the
  208.          execution of an instruction, in order to access data  bytes  which
  209.          are OPERANDS to the particular instruction  being  executed.  Such
  210.          would be the case if you  were  instructing  the  CPU  to  load  a
  211.          register with the contents of a  particular  memory  address.  The
  212.          data bytes following the  instruction  would  contain  the  memory
  213.          address to be used.
  214.    
  215.             There are a few instructions which direct the CPU  to  store  a
  216.          new value in the PC, rather than  advance  it.  These  are  called
  217.          JUMPS,  and  are  used  to  make  the  program   begin   executing
  218.          instuctions at a different address. This can  be  used  to  create
  219.          LOOPS in the program where a sequence of instructions is  executed
  220.          over and over again.
  221.    
  222.             Some of the "jump" instructions will only store the  new  value
  223.          in the PC if certain conditions are met,  such  as  the  last  ALU
  224.          operation resulted in zero, or did not result in zero. This allows
  225.          the program to alter  its  pattern  of  execution  based  on  data
  226.          values.
  227.    
  228.             For example, here is a program to count to 10 on a very  simple
  229.          imaginary computer. It shows the  use  of  IMMEDIATE  operands  to
  230.          instructions, which are shown by [PC+], and indicate  that  during
  231.          the execution of the instruction, the CPU  reads  the  next  value
  232.          from the address in the PC. The PC is advanced so that that  value
  233.          will not  be  executed  as  another  instruction  when  the  first
  234.          instruction is finished:
  235.    
  236.              Address   Interpretation of instruction value
  237.              ------------------------------------------------------
  238.                [0]     Load [PC+] data byte into register1
  239.                [1]     Data: 0
  240.                [2]     Add [PC+] data byte to register1
  241.                [3]     Data: 1
  242.                [4]     Load [PC+] data byte into register2
  243.                [5]     Data: 10
  244.                [6]     Subtract register1 from register2
  245.                [7]     Jump if result not zero to address in [PC+]
  246.                [8]     Data: 2
  247.                [9]     Halt CPU
  248.    Intro to DDS MICRO-C                                             Page: 5
  249.  
  250.  
  251.       2.2 Assembly Language
  252.    
  253.             In the preceeding section, you have learned how a CPU  executes
  254.          a program, and how a program may be coded in memory as a series of
  255.          instruction and data values. It should  be  obvious  to  you  that
  256.          although you can create programs in this way, it would be  a  long
  257.          and tedious job to write a program of any size using only  numeric
  258.          values.
  259.    
  260.             Not  only  is  it  very  hard  to  remember  the  hundreds   of
  261.          instruction  values  which  may  be  used   to   perform   certain
  262.          operations, but managing the memory address  which  are  coded  as
  263.          operands to the instructions becomes  a  real  headache.  This  is
  264.          particularily true when you  change  a  portion  of  the  program,
  265.          causing a change in the number of bytes of  memory  used  by  that
  266.          portion, and therefore  changes  all  of  the  memory  address  of
  267.          instructions and data which follow.
  268.    
  269.             To help ease the programming job, each of the CPU manufacturers
  270.          have defined an ASSEMBLY LANGUAGE for their CPU, which  represents
  271.          each of the machine operations with a more meaningful name  called
  272.          a MNEMONIC. Similar instructions may be  grouped  under  the  same
  273.          mnemonic with the individual instruction values determined by  the
  274.          operands.  For  example,  it  might  be  a  completely   different
  275.          instruction value which loads Register1 with  a  value  than  that
  276.          which loads register2. In assembly language you would use  similar
  277.          statements such as:
  278.    
  279.                LOAD R1,10
  280.                LOAD R2,10
  281.    
  282.             The  translation  from  mnemonics  to  instruction  values   is
  283.          performed by  a  program  called  an  ASSEMBLER.  In  addition  to
  284.          performing this translation, the assembler also allows LABEL names
  285.          to be assigned to addresses. The labels may be  referred  to  from
  286.          within other assembly  language  statements  instead  of  absolute
  287.          addresses.
  288.    
  289.             When written in assembly language, our "count  to  10"  program
  290.          would look something line this:
  291.    
  292.                    LOAD    R1,0
  293.            LOOP:   ADD     R1,1
  294.                    LOAD    R2,10
  295.                    SUB     R2,R1
  296.                    JMPNZ   LOOP
  297.                    HALT
  298.    
  299.             As  you  can  see,  the  above  program  would  be  much   more
  300.          understandable than a series of  numbers,  but  it  is  still  not
  301.          obvious to someone other that the author what the  intent  of  the
  302.          program is until he has followed through the loop, and  determined
  303.          what is accomplished by each instruction.
  304.    Intro to DDS MICRO-C                                             Page: 6
  305.  
  306.  
  307.             Imagine that you have just started a  new  job  as  a  computer
  308.          programmer, and your  manager  hands  you  a  listing  of  several
  309.          hundred pages, each of which is full of  assembly  language  lines
  310.          looking like the example  above,  and  says  "The  'SCAN'  command
  311.          causes corruption of the database search parameters. This is  VERY
  312.          important, could you stay and fix it tonight". You would have many
  313.          hours  (days?)  ahead  of  you  trying  to   determine   what   is
  314.          accomplished by each portion of the program. Now, imagine that the
  315.          assembly language looked more like this:
  316.    
  317.            ;
  318.            ; Simple demonstration program to show a counting loop
  319.            ;
  320.                    LOAD    R1,0        ; Begin with count of zero
  321.            ; Execute this loop once for each count
  322.            COUNT:  ADD     R1,1        ; Increment count
  323.                    LOAD    R2,10       ; Loop termination value
  324.                    SUB     R2,R1       ; Test R1, (result destroys R2)
  325.                    JMPNZ   COUNT       ; Repeat until we reach 10
  326.            ; We have reached 10 - All done
  327.                    HALT                ; Stop processing
  328.    
  329.             The text statements following the ';' characters in  the  above
  330.          example are called COMMENTS. They are completely  ignored  by  the
  331.          assembler, but are very useful to anyone attempting to  understand
  332.          the program.
  333.    
  334.       2.3 High Level Languages
  335.    
  336.             As you can see in the  preceeding  section,  assembly  language
  337.          programming offers much of  an  improvement  over  programming  by
  338.          direct instruction  values,  while  retaining  the  capability  to
  339.          control  EXACTLY  the  individual  operations  the  program   will
  340.          instruct the CPU to perform. Also, since the assembly language for
  341.          a particular CPU is defined by the manufacturer, you can  be  sure
  342.          that using it will allow you to take advantage  of  EVERY  feature
  343.          and capability that has been designed  into  that  particular  CPU
  344.          architecture.
  345.    
  346.             A good assembly language programmer can produce highly efficent
  347.          and compact programs because of this power. For  this  reason  you
  348.          will often see assembly  language  used  for  very  time  or  size
  349.          intensive applications.
  350.    Intro to DDS MICRO-C                                             Page: 7
  351.  
  352.  
  353.             It would seem that assembly language would be the ideal  method
  354.          of  doing  all  your  programming.  There  are  however,   several
  355.          drawbacks to using assembly language:
  356.    
  357.          1) Efficent use of assembly language often requires a  "different"
  358.             way of  looking  at  a  problem  and  strong  "logical"  mental
  359.             dicipline.
  360.             ** Not everyone is a good assembly language programmer **
  361.    
  362.          2) Assembly language source files are big.
  363.             ** It takes much codeing to perform even simple operations **
  364.             ** Significant time is spent entering source text **
  365.             ** Greater chance of error during design and entry **
  366.    
  367.          3) Poorly documented assembly language is undecipherable.
  368.             ** It is hard to maintain **
  369.    
  370.          4) Each assembly language is different and incompatible.
  371.             ** Programs will run on only one type of CPU **
  372.             ** Programmers have difficulty working on other CPUs **
  373.    
  374.             To help solve these problems,  there  are  a  number  of  "high
  375.          level"  programming  languages  available.  The  main   difference
  376.          between  assembly  and  high  level  languages  is  that  assembly
  377.          language produces only  one  CPU  instruction  for  each  language
  378.          "statement",  while  high  level  languages   can   produce   many
  379.          instructions for each "statement".
  380.    
  381.             High level languages attempt to provide a method of programming
  382.          by expressing ideas, rather than by directing the CPU  to  perform
  383.          each individual operation. When using a high level  language,  you
  384.          are freed from the task of keeping track of  register  and  memory
  385.          usage, and can concentrate  on  expressing  the  algorithms  which
  386.          accomplish the goal of the program.
  387.    
  388.             Here are some "high  level"  versions  of  our  "count  to  10"
  389.          program:
  390.    
  391.    
  392.        Basic:      100 FOR I=0 TO 10:NEXT I
  393.    
  394.        Fortran:        DO 100 i=0,10
  395.                    100 CONTINUE
  396.    
  397.        Forth:      11 0 DO LOOP
  398.    
  399.        'C':        for(i=0; i < 10; ++i);
  400.    Intro to DDS MICRO-C                                             Page: 8
  401.  
  402.  
  403.       2.4 Interpreters VS Compilers
  404.    
  405.             There  are   two   basic   types   of   high   level   language
  406.          implementations, INTERPRETERS and COMPILERS.
  407.    
  408.             An INTERPRETER is a program which reads  your  source  program,
  409.          and performs the actions indicated by  its  statements.  The  main
  410.          advantages to this approach are:
  411.    
  412.          1) FAST DEVELOPMENT:  Interpreters  often  include  complete  text
  413.             editors, which make it easy to  edit  and  debug  your  program
  414.             without leaving the interpreter. Also,  since  the  program  is
  415.             interpreted  directly,  there  is  no  waiting  to  compile  or
  416.             assemble it before you can try out a new change.
  417.    
  418.          2) EASY DEBUGGING:  Since  the  interpreter  is  actually  another
  419.             program, it will usually allow you to stop your program in  the
  420.             middle of execution, examine/modify  variables,  trace  program
  421.             flow, display callback stacks, etc. This makes  for  very  easy
  422.             debugging. Also, a good interpreter will perform  very  through
  423.             checking of your program as it interpretes,  thus  finding  and
  424.             reporting design errors which might otherwise show up  only  as
  425.             erratic and inconsistant program operation.
  426.    
  427.             And of course, there are drawbacks to interpreting:
  428.    
  429.          1) SLOW EXECUTION: The interpreter has to process  each  statement
  430.             in your program and determine what action is  to  be  performed
  431.             every time it encounters that statement. Many hundreds or  even
  432.             thousands of instructions are executed to accomplish  this  FOR
  433.             EACH STATEMENT.
  434.    
  435.          2) USES MEMORY: A good interpreter is a  fairly  complex  program,
  436.             and therefore occupies a substantial portion of system  memory,
  437.             meaning that less is available for your program & variables.
  438.    
  439.          3) DIFFICULTY OF USE: Once you are finished debugging,  you  would
  440.             like to  make  your  program,  as  easy  to  use  as  possible.
  441.             Unfortunatly, when using an interpreter,  you  always  have  to
  442.             load and execute the interpreter before loading  and  executing
  443.             your program.
  444.    
  445.             These disadvantages are so severe that interpreters are  rarely
  446.          used for serious programs which are to be  used  frequently  by  a
  447.          number of people. They are however, excellent learning  tools  for
  448.          the novice computer user.
  449.    Intro to DDS MICRO-C                                             Page: 9
  450.  
  451.  
  452.             A COMPILER is a program which reads your  source  program,  and
  453.          translates its statements into CPU INSTRUCTIONS which perform  the
  454.          specified function. Instead of actually executing your program, it
  455.          converts it to a form which can later be directly executed by  the
  456.          CPU. Its main advantages are:
  457.    
  458.          1) FAST EXECUTION: Since the program will be executed directly  by
  459.             the CPU, it will run much faster that  the  equivalent  program
  460.             being translated by an interpreter.
  461.    
  462.          2) LESS MEMORY: Although a compiler is a very complex program, and
  463.             uses lots of memory when it runs,  it  only  runs  once,  after
  464.             which your program is executed by itself directly by  the  CPU.
  465.             This means that the amount of memory required by  the  compiler
  466.             does not affect the amount of memory which is available for use
  467.             by your program when it runs.
  468.    
  469.          3) EASE OF USE: Since your program executes  by  itself,  you  can
  470.             load and execute it directly from the operating system  command
  471.             prompt.
  472.    
  473.             The main disadvantages of compilers over interpreters are:
  474.    
  475.          1) LONGER DEVELOPMENT: Many "traditional" compilers  require  that
  476.             you prepare your source program using a  separate  editor,  and
  477.             then save it to a disk  file,  and  submit  that  file  to  the
  478.             compiler. Every time you do this, you  have  to  wait  for  the
  479.             compiler to finish before you can even try your program.  NOTE:
  480.             some compiler vendors are  now  providing  integrated  editors,
  481.             eliminating the "save and exit" step, however you may not  like
  482.             the editor they have chosen for you.
  483.    
  484.          2) MORE  DIFFICULT  DEBUGGING:  Since  your  program  executes  by
  485.             itself, you have to run a standard system debugger  to  monitor
  486.             its execution. This will usually  be  somewhat  less  intuitive
  487.             than an interpreters built in debugging  features.  NOTE:  some
  488.             compiler  vendors  provide  a  "debug"  option  which  includes
  489.             debugging information in the program, and  a  special  debugger
  490.             which provides debugging facilities equal  to  or  better  than
  491.             those available from most interpreters.
  492.    
  493.       2.5 Object Modules & Linking
  494.    
  495.             Most assemblers and compilers available today support  the  use
  496.          of a LINKER. The linker is a program which  will  combine  several
  497.          previously compiled (or assembled) programs called OBJECT  MODULES
  498.          into a single larger executable  program.  This  helps  speed  the
  499.          development process by eliminating  the  need  to  re-compile  the
  500.          entire program when you have changed only one module.
  501.    Intro to DDS MICRO-C                                             Page: 10
  502.  
  503.  
  504.       2.6 Compiler Libraries
  505.    
  506.             Modern compilers promote  the  use  of  STRUCTURED  PROGRAMMING
  507.          techniques, which make programs easier to debug and maintain. I do
  508.          not propose to get into a  discussion  of  structured  programming
  509.          methods, but the main idea is to divide the  program  into  simple
  510.          parts, each of which performs a clearly defined function.
  511.    
  512.             Such functions often perform common algorithms required by many
  513.          programs, and  hence  are  made  into  compiler  LIBRARIES.  These
  514.          libraries are simply collections of small  useful  programs  which
  515.          may be used from within your programs without you having to  write
  516.          them. Most compiler manufacturers  provide  such  a  "library"  of
  517.          functions which they  believe  to  be  commonly  needed,  and  the
  518.          development tools necessary to link them with your programs.
  519.    
  520.       2.7 Portability
  521.    
  522.             One BIG advantage of high level languages is the fact that once
  523.          a program is written and running on one CPU, you can  usually  get
  524.          it  running  on  another  completely  different  CPU  with  little
  525.          difficulty. This is because although the CPUs are  different,  the
  526.          HIGH LEVEL LANGUAGE IS NOT CPU DEPENDANT AND REMAINS THE SAME. All
  527.          you have to do is to re-compile your  program,  using  a  compiler
  528.          which produces code for the new CPU.
  529.    
  530.             Actually, it usually takes a bit more effort than that, because
  531.          the language or library functions may  differ  slightly  from  one
  532.          implementation to another.
  533.    
  534.             This concept of PORTABILITY is one of the strong points of  the
  535.          'C' language, and you will see it  mentioned  from  time  to  time
  536.          throughout  this  manual.  In  addition  to  consistant   compiler
  537.          language implementation, 'C' benefits from very "standard" library
  538.          function definitions which are followed by most vendors.
  539.    Intro to DDS MICRO-C                                             Page: 11
  540.  
  541.  
  542.    3. INTRODUCTION TO 'C'
  543.    
  544.          'C' is a "high level" computer language,  which  has  become  very
  545.       popular in recent years. It has proven suitable for a  large  variety
  546.       of programming tasks, and unlike most other high level languages,  is
  547.       quite good for "low  level"  and  "system"  type  functions.  A  good
  548.       example of this capability is the popular  "UNIX"  operating  system,
  549.       which is  written  almost  entirely  in  'C'.  Before  UNIX,  it  was
  550.       generally thought that only assembly language was efficent enough for
  551.       writing an operating system.
  552.    
  553.          Programs in 'C' are divided into two main parts, VARIABLES,  which
  554.       are blocks of memory reserved for storing data, and FUNCTIONS,  which
  555.       are blocks of memory containing executable CPU instructions. They are
  556.       created using a DECLARATION STATEMENT, which is basically  a  command
  557.       to the compiler telling it what type of variable or function you wish
  558.       to create, and what values or instructions to place in it.
  559.    
  560.          There are several 'C' KEYWORDS which serve to inform the  compiler
  561.       of the size and type of a variable or function. This  information  is
  562.       used by the compiler to determine how to interpret the  value  STORED
  563.       in a VARIABLE, or RETURNED by a FUNCTION.
  564.    
  565.        Size:   int         - 16 bit value (default)
  566.                char        - 8 bit value
  567.        type:   unsigned    - Positive only (0-2**bits)
  568.                            + Default is signed (positive & negative)
  569.    
  570.        Examples:   int a;              /* 16 bit signed variable */
  571.                    char b;             /* 8 bit signed variable */
  572.                    unsigned int c;     /* 16 bit unsigned variable */
  573.                    unsigned d;         /* Also 16 bit unsigned variable */
  574.                    unsigned char e;    /* 8 bit unsigned variable */
  575.    
  576.          Normally, when you define a function or global variable, its  name
  577.       is made accessable to all object modules which will  be  linked  with
  578.       the program. You may access a  name  which  is  declared  in  another
  579.       module by  declaring  it  in  this  module  with  with  the  "extern"
  580.       modifier:
  581.    
  582.           extern int a;       /* external variable of type int    */
  583.           extern char b();    /* external function returning char */
  584.    
  585.          If you want to make sure that a function or global  variable  that
  586.       you are declaring is not accessable to  another  module  (To  prevent
  587.       conflicts with names in other modules etc), you can declare  it  with
  588.       the "static" modifier. This causes the name to be accessable only  by
  589.       functions within the module containing the "static" declaration:
  590.    
  591.                                 static int a;
  592.    Intro to DDS MICRO-C                                             Page: 12
  593.  
  594.  
  595.       3.1 Functions
  596.    
  597.             FUNCTIONS in 'C' are  collections  of  C  language  STATEMENTS,
  598.          which are grouped together under a name. Each statement represents
  599.          an operation which is to be performed by the CPU. For example, the
  600.          statement:
  601.    
  602.                                   A = A + 1;
  603.    
  604.          directs the CPU to read the variable called 'A', add a value of  1
  605.          to it, and to store the result back into the variable  'A'  (we'll
  606.          discuss variables in the next section). Note the  SEMICOLON  (';')
  607.          at the end  of  the  statement.  The  'C'  compiler  uses  ';'  to
  608.          determine when the statement ends. It does not care about lines or
  609.          spaces. For example, the above statement could also be written:
  610.    
  611.                                       A
  612.                                       =
  613.                                       A
  614.                                       +
  615.                                       1
  616.                                       ;
  617.    
  618.          and would still compile without error. Thus, you can have  a  VERY
  619.          long statement in 'C', which spans several lines. You must  always
  620.          however, be very careful to include the terminating ';'.
  621.    
  622.             Each function within a 'C' program can be "called" by using its
  623.          name in any statement, may accept "argument" values which  can  be
  624.          accessed by the statements contained within it, and may  return  a
  625.          value back to the caller. This allows functions in 'C' to be  used
  626.          as "building blocks", providing extensions to the language,  which
  627.          may be used from any other function.
  628.    
  629.             Below is a sample 'C' function,  which  performs  an  operation
  630.          (addition) on two argument values. The text between '/*' and  '*/'
  631.          is COMMENTS, and is ignored by the compiler.
  632.    
  633.            /* Sample 'C' function to add two numbers */
  634.            int add(num1, num2)     /* Declaration for function */
  635.                int num1, num2;     /* Declaration for arguments */
  636.            {
  637.                return num1+num2;   /* Send back sum of num1 and num2 */
  638.            }
  639.    
  640.             The names located within the  round  brackets  '()'  after  the
  641.          function name "add" tells the compiler what names you want to  use
  642.          to refer to the ARGUMENT VALUES. The "return" statement  tell  the
  643.          compiler that you want to terminate the execution of the function,
  644.          and return the value of  the  following  expression  back  to  the
  645.          caller. (We'll discuss "return" in more detail later).
  646.    Intro to DDS MICRO-C                                             Page: 13
  647.  
  648.  
  649.             Now that you have defined the function "add", you could use  it
  650.          in any other statement, in any function in your program, simply by
  651.          calling it with its name and argument values:
  652.    
  653.                                 a = add(1, 2);
  654.    
  655.             The above statement would call "add", and pass  it  the  values
  656.          '1' and '2' as arguments. "add" evaluates 1  +  2  to  be  3,  and
  657.          returns that value back, which is then stored in the variable 'a'.
  658.    
  659.             Note that 'C' uses the  round  brackets  following  a  name  to
  660.          determine that you wish to call the function, therefore, even if a
  661.          function has no argument values, you must include '()':
  662.    
  663.                                a = function();
  664.    
  665.             Also note, that if a function does not return a value,  or  you
  666.          do not want to  use  the  returned  value,  you  simply  code  the
  667.          function name by itself:
  668.    
  669.                                  function();
  670.    
  671.       3.2 Variables
  672.    
  673.             VARIABLES in 'C' are reserved areas of memory  where  the  data
  674.          manipulated by the program is stored. Each variable is assigned  a
  675.          name by which it  is  referenced  by  other  'C'  statements.  ALL
  676.          VARIABLES IN 'C' MUST BE DECLARED.
  677.    
  678.             Variables in 'C' may be single values as shown eariler, or they
  679.          may be declared as an ARRAY, which reserves  memory  space  for  a
  680.          number of data elements, each  with  the  type  declared  for  the
  681.          variable.
  682.    
  683.                                 int array[4];
  684.    
  685.             The above statement reserves memory  for  four  16  bit  signed
  686.          values, under the name "array". It is important to know  that  'C'
  687.          considers the elements of an array to be numbered from  zero  (0),
  688.          so the four locations in the above array are referenced by using:
  689.    
  690.                                    array[0]
  691.                                    array[1]
  692.                                    array[2]
  693.                                    array[3]
  694.    
  695.             There are two basic types  of  variables  in  'C',  GLOBAL  and
  696.          LOCAL.
  697.    Intro to DDS MICRO-C                                             Page: 14
  698.  
  699.  
  700.          3.2.1 GLOBAL Variables
  701.    
  702.                GLOBAL variables are set up permanently in memory, and exist
  703.             for the duration of the entire programs execution. The names of
  704.             global variables may be referenced by  any  statement,  in  any
  705.             function, at any time. Global variables are declared in 'C'  by
  706.             placing the declaration statement OUTSIDE of any function.  For
  707.             example:
  708.    
  709.                int a;      /* Declare GLOBAL variable */
  710.    
  711.                inita()     /* Function to initialize 'a' with 1 */
  712.                {
  713.                    a = 1;
  714.                }
  715.    
  716.                Note that the declaration statement for 'a' is NOT contained
  717.             within the definition of "inita".
  718.    
  719.                Since global variables are permanent blocks of memory, it is
  720.             possible to INITIALIZE them in the declaration statement.  This
  721.             causes the variable to be assigned a  value  at  COMPILE  time,
  722.             which will be loaded into memory at  the  same  time  that  the
  723.             program is loaded to be executed. This means that your  program
  724.             will not have to explicitly store a value in a.
  725.    
  726.                                   int a = 1;
  727.    
  728.                Array variables may also be initialized in  the  declaration
  729.             statement, by using the  curly  brackets  '{}'  to  inform  the
  730.             compiler that you have multiple values:
  731.    
  732.                           int a[4] = { 1, 2, 3, 4 };
  733.    
  734.                In MICRO-C, the initial values for an array are expressed as
  735.             a single string of values  REGUARDLESS  of  the  shape  of  the
  736.             array:
  737.    
  738.                         int a[2][2] = { 1, 2, 3, 4 };
  739.    
  740.                If an array has only one dimension (set of  '[]'s),  you  do
  741.             not have to specify the  size  of  initialized  variables.  The
  742.             compiler will automatically set  the  size  to  the  number  of
  743.             initial values given:
  744.    
  745.                         int array[] = { 1, 2, 3, 4 };
  746.    Intro to DDS MICRO-C                                             Page: 15
  747.  
  748.  
  749.          3.2.2 LOCAL Variables
  750.    
  751.                Variables  which  are  declared  WITHIN   a   function   are
  752.             determined by the compiler to be  LOCAL.  The  memory  used  by
  753.             these variables is automatically  reserved  when  the  function
  754.             begins to execute, and is released when it terminates. Names of
  755.             LOCAL variables are only accessable from  within  the  function
  756.             where they are defined:
  757.    
  758.                inita()     /* Function to initialize 'a' with 1 */
  759.                {
  760.                    int a;  /* Declare LOCAL variable */
  761.    
  762.                    a = 1;
  763.                }
  764.    
  765.                The  above  function  shows  the  declaration  of  a   local
  766.             variable, but is not very useful since the local variable  will
  767.             cease to exist when  the  function  returns.  Once  a  function
  768.             terminates, the content of its local variables is  lost.  Local
  769.             variables  are  used  as  temporary   locations   for   holding
  770.             intermediate values during a functions execution, which are not
  771.             required by any other part of the program.
  772.    
  773.                Each function may have its own local  variables,  but  since
  774.             memory is  only  used  by  the  functions  which  are  actually
  775.             executing, the total amount of memory reserved is usually  less
  776.             that the total size of all local variables in the program.
  777.    
  778.                Since local variables are allocated and released during  the
  779.             execution of your program, it is  not  possible  to  initialize
  780.             them at compile time, and therefore MICRO-C does not allow them
  781.             to be initialized in the declaration. Some compilers  do  allow
  782.             this, however,  the  code  generated  is  equivalent  to  using
  783.             assignment statements to initialize them at  the  beginning  of
  784.             the function.
  785.    
  786.                The ARGUMENTS to a function  (See  Functions)  are  actually
  787.             local variables for that function which are  created  when  the
  788.             function is called. For this reason,  the  argument  names  are
  789.             also un-available outside of the function  in  which  they  are
  790.             defined.
  791.    
  792.                NOTE: Local variables declared with  the  "static"  modifier
  793.             are a special case, and are  allocated  permanently  in  memory
  794.             like global  variables,  NOT  upon  entry  and  exit  from  the
  795.             function. This has several effects:
  796.    
  797.                - The variable may be initialized at compile time.
  798.                - The variable retains its  content  (and  occupies  memory)
  799.                  between calls to the function.
  800.                - If the function is called recursively  (see  later),  each
  801.                  instance of the function will access the same variable.
  802.    Intro to DDS MICRO-C                                             Page: 16
  803.  
  804.  
  805.       3.3 Pointers
  806.    
  807.             A POINTER in 'C' is a memory address,  which  can  be  used  to
  808.          access another data item in memory. All pointers in MICRO-C are 16
  809.          bit values, which allows access to a maximum  of  65536  bytes  of
  810.          memory through it.
  811.    
  812.             Any variable or function  may  be  declared  as  a  pointer  by
  813.          preceeding its name with the '*' character in the declaration:
  814.    
  815.            int *a;                 /* a = 16 bit pointer to int value */
  816.            char *b;                /* b = 16 bit pointer to char */
  817.            extern char *fgets();   /* Returns 16 bit pointer to char */
  818.    
  819.             Later on, I will show you how you can use  a  special  operator
  820.          called INDIRECTION to access data items at the  address  contained
  821.          in the pointer.
  822.    
  823.       3.4 A complete 'C' program
  824.    
  825.             With all of the preceeding  information  under  you  belt,  you
  826.          should be able to understand most  of  this  simple  but  complete
  827.          program:
  828.    
  829.            #include stdio.h
  830.    
  831.            /* Main program */
  832.            main()
  833.            {
  834.                int a, b, c;
  835.    
  836.                a = 1;
  837.                b = 2;
  838.                c = add(a, b);
  839.                printf("The result of (1+2)=%d\n", c);
  840.            }
  841.    
  842.            /* Our old familiar "add" function */
  843.            int add(num1, num2)
  844.                int num1, num2;
  845.            {
  846.                return num1+num2;
  847.            }
  848.    
  849.             Well... OK, perhaps you weren't quite ready for it. There are a
  850.          few new things  presented  in  this  program,  which  I  will  now
  851.          explain.
  852.    
  853.             First of all, you should know that the function name "main"  is
  854.          a special name which will be called at the  very  beginning,  when
  855.          the program is first run. It provides a starting  point  for  your
  856.          programmed functions. All 'C' programs have a "main" function.
  857.    Intro to DDS MICRO-C                                             Page: 17
  858.  
  859.  
  860.             You may also be wondering about those "#include"  and  "printf"
  861.          statements. This all comes back to the concept of PORTABILITY, and
  862.          has to do with the programs ability to perform  INPUT  and  OUTPUT
  863.          (I/O). Methods of performing  I/O  may  differ  greatly  from  one
  864.          operating system to another, and hence make it difficult to  write
  865.          "portable" programs. If you don't know  what  portability  is,  go
  866.          back and read the "Background Information" section.
  867.    
  868.             In order to insure that 'C' compilers could be  easily  adapted
  869.          to nearly any operating system,  the  designers  of  the  language
  870.          decided not to  include  ANY  I/O  capabilities  in  the  compiler
  871.          itself. By not implementing it, they didn't have  to  worry  about
  872.          it. All such activity is performed by a set of  functions  in  the
  873.          'C' STANDARD LIBRARY, which is provided for each operating system.
  874.    
  875.             These library functions are used in nearly all programs,  since
  876.          a program which can't read or  write  any  data  doesn't  do  much
  877.          useful work.
  878.    
  879.             Many of the library functions must be  declared  as  a  certain
  880.          type, which may be specific  to  the  compiler  implementation  or
  881.          operating system. (For example  the  "printf"  functions  must  be
  882.          declared as "register" in MICRO-C). The file "stdio.h" is provided
  883.          with  all  "standard  libraries",   and   contains   any   special
  884.          declarations required by the library functions.
  885.    
  886.             The "#include"  statement  causes  the  compiler  to  read  the
  887.          "stdio.h"  file,  and  to  process  the   declaration   statements
  888.          contained within it. This is equivalent to incorporating the  full
  889.          text of "stdio.h" at the beginning of your program.
  890.    
  891.             NOTE: If you are using a version of  MICRO-C  for  an  embedded
  892.          processor, this file is called "<cpu>io.h". For  example,  in  the
  893.          8051 developers kit, it is called "8051io.h".
  894.    
  895.             The "printf" statement is actually a call to a STANDARD LIBRARY
  896.          FUNCTION. It is available in almost all 'C'  implementations,  and
  897.          in the above example, displays the prompt "The result of  (1+2)=",
  898.          followed by the decimal value of the passed argument 'c'. For more
  899.          information about "printf" and other library functions,  refer  to
  900.          the MICRO-C Technical manual.
  901.    
  902.             At his point you may wish to enter  the  demonstration  program
  903.          into a file called "DEMO1.C", and  compile  it  with  the  MICRO-C
  904.          compiler. Remember that 'C' IS CASE SENSITIVE, so be sure to enter
  905.          the program EXACTLY as it is shown. Also, make sure that  you  are
  906.          positioned in the MICRO-C directory before you  create  the  file.
  907.          After entering and saving the file with your favorite text editor,
  908.          compile the program using the command:
  909.    
  910.                                    CC DEMO1
  911.    
  912.             You can  run  the  resultant  "DEMO1.COM"  program,  by  simply
  913.          typeing "DEMO1", at the DOS command prompt.
  914.    Intro to DDS MICRO-C                                             Page: 18
  915.  
  916.  
  917.       3.5 'C' memory organization
  918.    
  919.             Now that you have seen a complete 'C'  program,  and  know  the
  920.          basic concepts of functions and variables, you may  want  to  know
  921.          how MICRO-C organizes the computer memory  when  these  constructs
  922.          are used. Knowing this  may  help  you  understand  functions  and
  923.          variables more precicely.
  924.    
  925.             The information in this section is  not  really  necessary  for
  926.          casual use of the language, if you feel  that  such  detail  would
  927.          only confuse you, feel free to skip it until later.
  928.    
  929.             The MICRO-C compiler builds your program to occupy a  block  of
  930.          memory. In the case of small 8 bit computers, this block of memory
  931.          will usually be the entire free ram in the machine. In the case of
  932.          larger machines, it will usually be 64K (65536 bytes), but may  be
  933.          larger or smaller depending on the implementation.
  934.    
  935.             The exact size of the memory block  is  unimportant,  since  it
  936.          affects only the maximum size of a MICRO-C program. The methods of
  937.          memory allocation remain the same.
  938.    
  939.          3.5.1 Static memory
  940.    
  941.                MICRO-C places all of the executable code from the  compiled
  942.             functions at the very  beginning  of  the  memory  block.  This
  943.             includes all  CPU  instructions  which  are  generated  by  the
  944.             compiler. MICRO-C places all initialized  global  and  "static"
  945.             local variables in this area as well, and also something called
  946.             the LITERAL POOL.
  947.    
  948.                The "literal pool" consists of all string data which is used
  949.             in statements or initializations in the program. An example  of
  950.             this is the string used in the preceeding demonstration program
  951.             ("Result of (1+2)=%d\n"), which is  a  series  of  data  bytes,
  952.             which are passed to the "printf" function.
  953.    
  954.                This collection of CPU  instructions,  Initialized  variable
  955.             data, and literal pool data is the complete program image which
  956.             must be loaded into memory every time the program is executed.
  957.    
  958.                The next section of memory allocated by  MICRO-C  holds  the
  959.             global  and  static  local  variables  which  have   not   been
  960.             initialized. Since they have no initial  values,  they  do  not
  961.             have to be loaded every time the program runs. This also  means
  962.             that until the program stores a value in  a  particular  memory
  963.             location its contents will be some random value which  happened
  964.             to be at that location in memory before the program was loaded.
  965.    
  966.                All of this memory is called "STATIC" memory, because it  is
  967.             reserved for code and data at COMPILE time. Once the program is
  968.             compiled, the above mentioned items are fixed  in  memory,  and
  969.             cannot be moved or changed in size.
  970.    Intro to DDS MICRO-C                                             Page: 19
  971.  
  972.  
  973.          3.5.2 Dynamic memory
  974.    
  975.                When your program begins execution, one of the first  things
  976.             that happems, is that a STACK is set up at the very top of  the
  977.             memory block. This  stack  is  always  referenced  by  a  STACK
  978.             POINTER register which always points to the lowest  address  of
  979.             memory used on the stack. All memory in  the  block  above  the
  980.             stack pointer is deemed to be in use. This is usually  a  built
  981.             in feature of the CPU.
  982.    
  983.                At the beginning of every function,  the  code  produced  by
  984.             MICRO-C contains instructions to reduce the value of the  stack
  985.             pointer by the number of bytes of memory required by the  local
  986.             variables in that function.  When  the  function  "returns"  or
  987.             terminates, the stack pointer is increased by the same amount.
  988.    
  989.                This allows the function to use the memory immediatly  above
  990.             the new stack pointer for its local variables without fear that
  991.             another function will also try to use it. When another function
  992.             is called, it will reserve its memory BELOW the memory  already
  993.             in use by the calling  function,  and  will  return  the  stack
  994.             pointer when it is finished. Thus, all local variables  may  be
  995.             accessed as constant offsets from the stack pointer set  up  at
  996.             the beginning of the function.
  997.    
  998.                ARGUMENTS to a function are passed by  reserving  memory  on
  999.             the stack, and setting it to the argument values, just PRIOR to
  1000.             calling the function. When the  called  function  returns,  the
  1001.             stack reserved for its arguments is  removed  by  the  function
  1002.             performing the call. In this way, the arguments are  just  more
  1003.             local variables, and may also be accessed as  constant  offsets
  1004.             from the stack pointer.
  1005.    
  1006.          3.5.3 Heap memory
  1007.    
  1008.                Some programs need temporary memory which will not disappear
  1009.             when the function terminates, or they may not  know  the  exact
  1010.             amount of memory they need for a certain operations until  some
  1011.             calculations have been performed.
  1012.    
  1013.                To resolve these problems,  'C'  provides  another  type  of
  1014.             dynamic memory which is called "HEAP" memory. To  make  use  of
  1015.             this memory, the program uses the "malloc" function  (from  the
  1016.             standard library)  which  allocates  a  block  of  memory,  and
  1017.             returns a pointer value to its address. The  program  may  then
  1018.             access and manipulate this memory through the pointer.
  1019.    
  1020.                When the program is finished with the memory,  it  may  then
  1021.             use the "free" library function to  release  it,  and  make  it
  1022.             available for use by other calls to "malloc".
  1023.    
  1024.                A program may continue allocating  memory  via  "malloc"  as
  1025.             long as there is available free memory to allocate. The library
  1026.             functions will  keep  track  of  which  blocks  of  memory  are
  1027.             allocated, and which blocks are available for allocation.
  1028.    Intro to DDS MICRO-C                                             Page: 20
  1029.  
  1030.  
  1031.             A typical memory layout for a 'C'  program  in  the  middle  of
  1032.          execution might look something like this:
  1033.    
  1034.                +----------------------------------------+
  1035.                |            CPU Instructions            |
  1036.                |         which make up program          |  *1
  1037.                |                "code"                  |
  1038.                +----------------------------------------+
  1039.                |      Initialized GLOBAL variables      |
  1040.                |                 and                    |  *1
  1041.                |  Initialized "static" LOCAL variables  |
  1042.                +----------------------------------------+
  1043.                |           LITERAL POOL data            |  *1
  1044.                +----------------------------------------+
  1045.                |     Uninitialized GLOBAL variables     |
  1046.                |                 and                    |      
  1047.                | Uninitialized "static" LOCAL variables |
  1048.                +----------------------------------------+
  1049.                |      Memory allocated to the heap      |
  1050.                +----------------------------------------+
  1051.                |          (Heap grows upward)           |
  1052.                |                   |                    |
  1053.                |  Free memory, available for growth of  |
  1054.                |           the heap and stack.          |
  1055.                |                   |                    |
  1056.                |         (Stack grows downward)         |
  1057.                +----------------------------------------+
  1058.                | Local variables of innermost function  |  *2
  1059.                +----------------------------------------+
  1060.                |  Return address of innermost function  |
  1061.                +----------------------------------------+
  1062.                |     Arguments of innermost function    |
  1063.                +----------------------------------------+
  1064.                |   Local variables of middle function   |  *2
  1065.                +----------------------------------------+
  1066.                |   Return address of middle function    |
  1067.                +----------------------------------------+
  1068.                |      Arguments of middle function      |
  1069.                +----------------------------------------+
  1070.                |    Local variables of main function    |  *2
  1071.                +----------------------------------------+
  1072.                |    Return address of main function     |
  1073.                +----------------------------------------+
  1074.    
  1075.            *1 = Only these blocks of memory need to be loaded from disk
  1076.                 when the program is started.
  1077.    
  1078.            *2 = Other than "static" local variables.
  1079.    
  1080.             For those not familiar with computer architecture,  the  RETURN
  1081.          ADDRESS is placed on the stack by a CALL INSTRUCTION, and  is  the
  1082.          memory address immediately  following  that  instruction.  When  a
  1083.          RETURN INSTRUCTION is later executed, the CPU removes  the  return
  1084.          address from the stack, and places it in the PROGRAM COUNTER, thus
  1085.          causing  program  execution  to  resume   with   the   instruction
  1086.          immediately following the original call instruction.
  1087.    Intro to DDS MICRO-C                                             Page: 21
  1088.  
  1089.  
  1090.    4. EXPRESSIONS
  1091.    
  1092.          An expression in 'C' consists of one or more values, and OPERATORS
  1093.       which cause those values to be modified in  a  calculation.  Anywhere
  1094.       that you would use a simple  value  in  'C',  you  can  also  use  an
  1095.       expression. We have already seen that with the "return" statement  in
  1096.       the "add" function in our example program. Knowing that  we  can  use
  1097.       expressions and values interchangably, we could shorten  the  example
  1098.       "main" function to:
  1099.    
  1100.            main()
  1101.            {
  1102.                int a, b;
  1103.    
  1104.                a = 1;
  1105.                b = 2;
  1106.                printf("The result of (1+2)=%d\n", add(a,b));
  1107.            }
  1108.    
  1109.        or even:
  1110.    
  1111.            main()
  1112.            {
  1113.                int a, b;
  1114.    
  1115.                a = 1;
  1116.                b = 2;
  1117.                printf("The result of (1+2)=%d\n", a+b);
  1118.            }
  1119.    
  1120.        or even:
  1121.    
  1122.            main()
  1123.            {
  1124.                printf("The result of (1+2)=%d\n", 1 + 2);
  1125.            }
  1126.    
  1127.        Or, if we wanted the 'a, b & c' variables set anyway:
  1128.    
  1129.            /* Note the use or round brackets '()' to incorporate
  1130.               a SUB-EXPRESSION into the main expression */
  1131.            main()
  1132.            {
  1133.                int a, b, c;
  1134.    
  1135.                printf("The result of (1+2)=%d\n", c = (a = 1) + (b = 2));
  1136.            }
  1137.    
  1138.          You can see that an entire expression, including three ASSIGNMENTS
  1139.       was included in a place where only a simple value is  used.  This  is
  1140.       one of the great powers of 'C', and can result  in  very  small  fast
  1141.       efficent code (at the expense of readability). Numerous  examples  of
  1142.       this type of programming may by found in  the  source  code  for  the
  1143.       MICRO-C compiler.
  1144.    Intro to DDS MICRO-C                                             Page: 22
  1145.  
  1146.  
  1147.       4.1 Unary operators
  1148.    
  1149.             Unary (single operand)  operators  are  those  operators  which
  1150.          perform a computation on only a single value. In most  cases,  the
  1151.          operator must be placed immediatly BEFORE the value to be operated
  1152.          on.
  1153.    
  1154.          4.1.1 Negate: -
  1155.    
  1156.                The NEGATE operator causes the value  to  its  right  to  be
  1157.             changed in sign. Thus, a positive value will be converted to  a
  1158.             negative value (of the same magnitude) and vice  versa.  It  is
  1159.             most often used to enter negative numbers, but it is  perfectly
  1160.             legal to apply this operator to a variable or expression.
  1161.    
  1162.            eg:     a = -5;         /* a = negative 5 */
  1163.                    b = 10;         /* b = positive 10 */
  1164.                    c = -b;         /* c = -10 */
  1165.                    d = -(b+5);     /* d = -15 */
  1166.                    e = -b+5;       /* e = -5  *
  1167.                    f = -a;         /* f = 5   */
  1168.    
  1169.          4.1.2 Bitwise Complement: ~
  1170.    
  1171.                The BITWISE COMPLEMENT operator reverses the value (0 or  1)
  1172.             of each individual BIT in the value to its right. This is  very
  1173.             useful when used with the other BITWISE operators (AND, OR  and
  1174.             XOR), to perform test on combinations of bits in a byte  (char)
  1175.             or word (int).
  1176.    
  1177.            eg:     a = 5;          /* a = 00000101 */
  1178.                    b = ~a;         /* b = 11111010 */
  1179.    
  1180.          4.1.3 Logical Complement: !
  1181.    
  1182.                The LOGICAL COMPLEMENT operator reverse the "logical  sense"
  1183.             (TRUE or FALSE) of the value to its right. In 'C'  a  value  is
  1184.             considered to be logically TRUE if it contains any value  other
  1185.             than zero. A value of zero is considered to be logically FALSE.
  1186.             The logical complement gives a value of  zero  (FALSE)  if  the
  1187.             original value was non-zero, and a value of one (TRUE)  if  the
  1188.             original value was zero. You will  see  later  that  there  are
  1189.             CONDITIONAL statements in 'C', which perform certain operations
  1190.             only if values are TRUE. This operator provides a simple method
  1191.             of reversing those conditions to occur when the value is FALSE.
  1192.    
  1193.            eg:     if(a) b = 10;   /* Set b to 10 if a is TRUE */
  1194.                    if(!a) b = 10;  /* Set b to 10 if a is FALSE */
  1195.    Intro to DDS MICRO-C                                             Page: 23
  1196.  
  1197.  
  1198.          4.1.4 Increment: ++
  1199.    
  1200.                The INCREMENT operator must be used on a value that  can  be
  1201.             ASSIGNED (such as a variable or array element). It  causes  the
  1202.             value to be INCREASED by one (except for a  special  case  with
  1203.             POINTERS which are advanced by the size of the  type  to  which
  1204.             they point).
  1205.    
  1206.                Unlike most other unary operators,  the  increment  operator
  1207.             may be placed either BEFORE or AFTER  the  value,  and  behaves
  1208.             slightly differently  depending  on  its  position.  If  placed
  1209.             BEFORE the value, the variable  is  incremented,  and  the  new
  1210.             value is passed on as the result. If placed  AFTER  the  value,
  1211.             the original value is passed on as the result, and the variable
  1212.             is then incremented.
  1213.    
  1214.            eg:     a = b = 10;     /* Set a & b to 10 */
  1215.                    c = ++a;        /* c = 11 (a = 11) */
  1216.                    d = b++;        /* d = 10 (b = 11) */
  1217.    
  1218.          4.1.5 Decrement: --
  1219.    
  1220.                The  DECREMENT  operator  behaves  exactly   the   same   as
  1221.             increment,  except  that  the  value  is  REDUCED  instead   of
  1222.             increased.
  1223.    
  1224.            eg:     a = b = 10;     /* Set a & b to 10 */
  1225.                    c = --a;        /* c = 9  (a=9) */
  1226.                    d = b--;        /* d = 10 (b=9) */
  1227.    
  1228.          4.1.6 Indirection: *
  1229.    
  1230.                The INDIRECTION operator may only be applied to POINTERS, or
  1231.             expressions which result in a  POINTER  VALUE.  It  causes  the
  1232.             memory contents at the address contained in the pointer  to  be
  1233.             accessed, instead of the pointer value itself.
  1234.    
  1235.            eg:     char *ptr;      /* Declare a pointer to character */
  1236.                    ptr = 10;       /* Set pointer variable to 10 */
  1237.                    *ptr = 5;       /* Set 'char' at address 10 to 5 */
  1238.                    a = ptr;        /* a = 10 (pointer value) */
  1239.                    b = *ptr;       /* b = 5 (Indirect through address 10) */
  1240.    
  1241.          4.1.7 Address: &
  1242.    
  1243.                The ADDRESS operator may only be used on a value  which  can
  1244.             be ASSIGNED (such as a variable or array element).  It  returns
  1245.             the memory address of the value, instead of the value itself.
  1246.    
  1247.            eg:     a = 10;         /* Set variable a to 10 */
  1248.                    ptr = &a;       /* Get address of 'a' */
  1249.                    b = *ptr;       /* b = 10 (contents of 'a') */
  1250.                    *ptr = 15;      /* Store 15 at address of 'a' */
  1251.                    c = a;          /* c = 15 */
  1252.    Intro to DDS MICRO-C                                             Page: 24
  1253.  
  1254.  
  1255.       4.2 Binary Operators
  1256.    
  1257.             In additon to the "unary" operators presented above, 'C' has  a
  1258.          large complement of BINARY (two  operand)  operators.  The  binary
  1259.          operators take two values, presented on the left and right side of
  1260.          the operator, and combine them into some form of computed value.
  1261.    
  1262.          4.2.1 Addition: +
  1263.    
  1264.                The ADDITION operator computes the SUM of two values.
  1265.    
  1266.            eg:     a = b + 5;      /* a = sum of b and 5 */
  1267.    
  1268.          4.2.2 Subtraction: -
  1269.    
  1270.                The SUBTRACTION operator  computes  the  DIFFERENCE  of  two
  1271.             values.
  1272.    
  1273.            eg:     a = b - 5;      /* a = difference of b and 5 */
  1274.    
  1275.          4.2.3 Multiplication: *
  1276.    
  1277.                The MULTIPLICATION operator  computes  the  PRODUCT  of  two
  1278.             values.
  1279.    
  1280.            eg:     a = b * 5;      /* a = b multiplied by 5 */
  1281.    
  1282.          4.2.4 Division: /
  1283.    
  1284.                The DIVISION operator computes the QUOTIENT  resulting  from
  1285.             the division of the left value by the right value.
  1286.    
  1287.    
  1288.            eg:     a = b / 5;      /* a = b divided by 5 */
  1289.    
  1290.          4.2.5 Modulus: %
  1291.    
  1292.                The MODULUS operator computes the REMAINDER  resulting  from
  1293.             the division of the left value by the right value.
  1294.    
  1295.            eg:     a = b % 5;      /* a = remainer of b divided by 5 */
  1296.    
  1297.          4.2.6 Bitwise And: &
  1298.    
  1299.                The BITWISE AND operator performs an AND  function  on  each
  1300.             pair of bits between the values. Bit positions which have a one
  1301.             (1) bit in BOTH values will receive a one in  the  result.  All
  1302.             other bit positions will receive zero (0).
  1303.    
  1304.            eg      a = 5;          /* a = 00000101 */
  1305.                    b = 6;          /* b = 00000110 */
  1306.                    c = a & b;      /* c = 00000100 (4) */
  1307.    Intro to DDS MICRO-C                                             Page: 25
  1308.  
  1309.  
  1310.          4.2.7 Bitwise Or: |
  1311.    
  1312.                The BITWISE OR operator performs an OR function on each pair
  1313.             of bits between the values. Bit positions which have a one  (1)
  1314.             in EITHER value will receive a one in the result. All other bit
  1315.             positions will receive zero (0).
  1316.    
  1317.            eg      a = 5;          /* a = 00000101 */
  1318.                    b = 6;          /* b = 00000110 */
  1319.                    c = a | b;      /* c = 00000111 (7) */
  1320.    
  1321.          4.2.8 Bitwise Exclusive Or: ^
  1322.    
  1323.                The BITWISE EXCLUSIVE OR operator performs an  EXCLUSIVE  OR
  1324.             function on each pair of bits between the values. Bit positions
  1325.             which have a one (1) in EITHER value, but NOT  IN  BOTH  values
  1326.             will receive a one in the result. All other bit positions  will
  1327.             receive zero (0).
  1328.    
  1329.            eg      a = 5;          /* a = 00000101 */
  1330.                    b = 6;          /* b = 00000110 */
  1331.                    c = a ^ b;      /* c = 00000011 (3) */
  1332.    
  1333.          4.2.9 Logical And: &&
  1334.    
  1335.                The LOGICAL AND operator returns  TRUE  (non-zero)  only  if
  1336.             BOTH values are TRUE. If either value is FALSE, FALSE (zero) is
  1337.             returned.
  1338.    
  1339.                MICRO-C accomplishes this by evaluating the left value,  and
  1340.             returning zero (FALSE) if it is equal to  zero,  otherwise  the
  1341.             right value is evaluated and returned. Some 'C' compilers force
  1342.             the returned value to be either zero (0) or one (1).
  1343.    
  1344.            eg:     if(a && b)
  1345.                        printf("Both 'a' AND 'b' are TRUE");
  1346.    
  1347.          4.2.10 Logical Or: ||
  1348.    
  1349.                The LOGICAL OR operator returns TRUE  (non-zero)  if  EITHER
  1350.             value is true, if  both  values  are  FALSE,  FALSE  (zero)  is
  1351.             returned.
  1352.    
  1353.                MICRO-C accomplishes this by evaluating the left value,  and
  1354.             returning its value if it is not  zero  (TRUE),  otherwise  the
  1355.             right value is evaluated and returned. Some 'C' compilers force
  1356.             the returned value to be either zero (0) or one (1).
  1357.    
  1358.            eg:     if(a || b)
  1359.                        printf("Either 'a' OR 'b' is TRUE");
  1360.    Intro to DDS MICRO-C                                             Page: 26
  1361.  
  1362.  
  1363.          4.2.11 Shift Left: <<
  1364.    
  1365.                The SHIFT LEFT operator returns a value which  is  equal  to
  1366.             the left value shifted left by a number of bits  equal  to  the
  1367.             right value.
  1368.    
  1369.            eg:     a = 10;         /* a = 00001010 */
  1370.                    b = a << 3;     /* b = 01010000 (80) */
  1371.    
  1372.          4.2.12 Shift Right: >>
  1373.    
  1374.                The SHIFT RIGHT operator returns a value which is  equal  to
  1375.             the left value shifted right by a number of bits equal  to  the
  1376.             right value.
  1377.    
  1378.            eg:     a = 80;         /* a = 01010000 */
  1379.                    b = a >> 3;     /* b = 00001010 (10) */
  1380.    
  1381.          4.2.13 Equals: ==
  1382.    
  1383.                The EQUALS operator performs  a  test  of  the  values,  and
  1384.             returns a one (1) of they are identical. If they do not  match,
  1385.             a zero (0). is returned. NOTE a common  difficulty  encountered
  1386.             when learning 'C' is to confuse the EQUALS (==) and  ASSIGNMENT
  1387.             (=) operators.
  1388.    
  1389.            eg:     if(a == 10)
  1390.                        printf("a is equal to 10");
  1391.    
  1392.          4.2.14 Not Equals: !=
  1393.    
  1394.                The NOT EQUALS operator perform a test of  the  two  values,
  1395.             and returns a one (1) if they are NOT identical. If the  values
  1396.             match, a zero (0) is returned.
  1397.    
  1398.            eg:     if(a != 10)
  1399.                        printf("a is not equal to 10");
  1400.    Intro to DDS MICRO-C                                             Page: 27
  1401.  
  1402.  
  1403.          4.2.15 Greater Than: >
  1404.    
  1405.                The GREATER THAN operator performs a test of the two values,
  1406.             and returns a one (1) is the left  value  is  higher  than  the
  1407.             right value. If the left value is equal to  or  less  than  the
  1408.             right value, zero (0) is returned.
  1409.    
  1410.            eg:     if(a > 10)
  1411.                        printf("a is bigger than 10");
  1412.    
  1413.          4.2.16 Less Than: <
  1414.    
  1415.                The LESS THAN operator performs a test of  the  two  values,
  1416.             and returns a one (1) is the left value is lower than the right
  1417.             value. If the left value is equal to or greater than the  right
  1418.             value, zero (0) is returned.
  1419.    
  1420.            eg:     if(a < 10)
  1421.                        printf("a is smaller than 10");
  1422.    
  1423.          4.2.17 Greater Than or Equals: >=
  1424.    
  1425.                The GREATER THAN OR EQUALS operator performs a test  of  the
  1426.             two values, and returns a one (1) is the left value  is  higher
  1427.             than OR equal to the right value. If the  left  value  is  less
  1428.             than the right value, zero (0) is returned.
  1429.    
  1430.            eg:     if(a >= 10)
  1431.                        printf("a is bigger than or equal to 10");
  1432.    
  1433.          4.2.18 Less Than or Equals: <=
  1434.    
  1435.                The LESS THAN OR EQUALS operator performs a test of the  two
  1436.             values, and returns a one (1) is the left value is  lower  than
  1437.             OR equal to the right value. If the left value is greater  than
  1438.             the right value, zero (0) is returned.
  1439.    
  1440.            eg:     if(a <= 10)
  1441.                        printf("a is smaller than or equal to 10");
  1442.    Intro to DDS MICRO-C                                             Page: 28
  1443.  
  1444.  
  1445.          4.2.19 Assignment: =
  1446.    
  1447.                The ASSIGNMENT operator takes the value to  the  right,  and
  1448.             STORES it in the left value. The left value must be ASSIGNABLE.
  1449.    
  1450.            eg:     a = 10;     /* Store 10 in variable a */
  1451.    
  1452.          4.2.20 Self Assignment Operators
  1453.    
  1454.                'C' provides special operators which implement  a  shorthand
  1455.             method of performing an operation on two values when the result
  1456.             is stored back into the left value. These operators are  called
  1457.             SELF ASSIGNMENT operators.
  1458.    
  1459.                       Shorthand:          Equivalent to:
  1460.                    --------------------------------------
  1461.                        a += 1;             a = a + 1;
  1462.                        b -= 2;             b = b - 2;
  1463.                        c *= 3;             c = c * 3;
  1464.                        d /= 4;             d = d / 4;
  1465.                        e %= 5;             e = e % 5;
  1466.                        f &= 6;             f = f & 6;
  1467.                        g |= 7;             g = g | 7;
  1468.                        h ^= 8;             h = h ^ 8;
  1469.                        i <<= 9;            i = i << 9;
  1470.                        j >>= 10;           j = j >> 10;
  1471.    
  1472.                With most compilers, the self assignment  operators  do  not
  1473.             produce any better  code  when  using  simple  variables.  They
  1474.             simply allow you to state what you want done in  a  more  clear
  1475.             and concise manner.
  1476.    
  1477.                With MICRO-C, and most non-optimizing compilers, there is an
  1478.             advantage  to  using  the  self   assignment   operators   when
  1479.             referencing a CALCULATED ADDRESS (Such  as  when  accessing  an
  1480.             indexed array).
  1481.    
  1482.                                 array[a] += b;
  1483.    
  1484.                          Is often more efficent than:
  1485.    
  1486.                            array[a] = array[a] + b;
  1487.    Intro to DDS MICRO-C                                             Page: 29
  1488.  
  1489.  
  1490.       4.3 Other Operators
  1491.    
  1492.             There are a few 'C' operators which do not fall into one of the
  1493.          above clearly defined classes. Those operators are presented here:
  1494.    
  1495.          4.3.1 Statement terminator: ;
  1496.    
  1497.                We have already seen the ';' STATEMENT TERMINATOR,  this  is
  1498.             just a reminder of how important it is. Leaving out the ';'  at
  1499.             the end of a statement is a good way to convince  the  compiler
  1500.             to produce lots of error messages.
  1501.    
  1502.          4.3.2 Comma Operator: ,
  1503.    
  1504.                The function performed by the COMMA operator ',' depends  on
  1505.             where it occurs in the 'C' source file.
  1506.    
  1507.                When used within the  arguments  to  a  function  call,  its
  1508.             function is to separate each argument that is passed:
  1509.    
  1510.            eg:     function(a, b, c);
  1511.    
  1512.                When used in a DECLARATION statement,  its  function  is  to
  1513.             separate each variable name to be defined:
  1514.    
  1515.                eg: int a, b, c;
  1516.    
  1517.                When used in a global variable initialization, its  function
  1518.             is to separate the initial elements:
  1519.    
  1520.            eg:     int array[] = { 1, 2, 3 };
  1521.    
  1522.                When used in  any  expression  other  than  those  mentioned
  1523.             above, a comma allows several expressions to be used in a place
  1524.             where only one expression is expected. The  value  returned  in
  1525.             that of the RIGHTMOST expression:
  1526.    
  1527.            eg:     return a=4, 10;     /* Set a = 4, and return 10 */
  1528.    Intro to DDS MICRO-C                                             Page: 30
  1529.  
  1530.  
  1531.          4.3.3 Conditional Operator: ?
  1532.    
  1533.                The CONDITIONAL operator  allows  you  to  create  a  single
  1534.             expression which evaluates one of two SUB-EXPRESSIONS depending
  1535.             on a logical condition. It is coded in the 'C'  source  program
  1536.             in the form:
  1537.    
  1538.              <condition> ? <TRUE expression> : <FALSE expression>
  1539.    
  1540.                Consider, the standard  library  function  "toupper",  which
  1541.             converts any  lower  case  character  to  upper  case.  If  the
  1542.             original character was lower case, no conversion is  made,  and
  1543.             the character is returned unchanged.
  1544.    
  1545.                Knowing that in ASCII, lower case characters  have  a  value
  1546.             equal to the equivalent upper case character  +  64,  we  could
  1547.             code the following function:
  1548.    
  1549.                /* Function to convert lower case to upper case */
  1550.                char toupper(chr)
  1551.                    char chr;
  1552.                {
  1553.                    if((chr >= 'a') && (chr <= 'z'))    /* lower case ? */
  1554.                        return chr - 64;                /* Convert */
  1555.                    else
  1556.                        return chr;                     /* Leave alone */
  1557.                }
  1558.    
  1559.                The same function coded using a conditional expression is:
  1560.    
  1561.                /* Function to convert lower case to upper case */
  1562.                char toupper(chr)
  1563.                    char chr;
  1564.                {
  1565.                    return (chr >= 'a') && (chr <= 'z') ? chr - 64 : chr;
  1566.                }
  1567.    
  1568.                Although the difference between the above two functions  may
  1569.             seem  trivial,  remember  that  you  can  use  ANY   expression
  1570.             (including a CONDITIONAL expression) anywhere  that  you  could
  1571.             place a simple value. Once you get the hang of that,  you  will
  1572.             find that conditional expressions are a very  powerful  feature
  1573.             of the 'C' language.
  1574.    Intro to DDS MICRO-C                                             Page: 31
  1575.  
  1576.  
  1577.          4.3.4 Round Brackets: ( )
  1578.    
  1579.                The ROUND BRACKETS are used by 'C' to perform two functions.
  1580.             First, as already mentioned, they identify function calls,  and
  1581.             hold any arguments which are being passed:
  1582.    
  1583.            eg:     function1();
  1584.                    function2(a);
  1585.                    function3(a, b);
  1586.    
  1587.                The round brackets are also used to set up a SUB EXPRESSION,
  1588.             which can be used within another expression as a simple value:
  1589.    
  1590.            For example:
  1591.    
  1592.                    b = a + 5;
  1593.                    c = b / 2;
  1594.    
  1595.            Can be replaced by:
  1596.    
  1597.                    c = (a + 5) / 2;
  1598.    
  1599.            Or, if you want 'b' assigned:
  1600.    
  1601.                    c = (b = a + 5) / 2;
  1602.    
  1603.          4.3.5 Square Brackets: [ ]
  1604.    
  1605.                The SQUARE BRACKETS are used to perform indexing.  Variables
  1606.             which  have  been  declared   as   ARRAYS   may   be   indexed.
  1607.             MULTIDIMENSIONAL arrays may be  indexed  by  using  a  pair  of
  1608.             square brackets for each dimension:
  1609.    
  1610.            eg:     int array1[4], array2[2][2];
  1611.    
  1612.                    array1[0] = 10;
  1613.                    a = array1[1];
  1614.                    b = array2[1][0];
  1615.    
  1616.                If a multidimensional array is  indexed  with  a  number  of
  1617.             square  bracket  pairs  which  is  less  that  the  number   of
  1618.             dimsnsions of the array, the value returned is a POINTER  VALUE
  1619.             to the beginning address of the next dimension. A  pointer  may
  1620.             be indexed as it they were single dimension array,  the  memory
  1621.             offsets added to the pointer will be calculated  based  on  the
  1622.             size of the data type to which it has been declared to point:
  1623.    
  1624.            eg:     int array[3][3], *ptr;
  1625.    
  1626.                    array[2][1] = 10;
  1627.                    ptr = array[2];
  1628.                    a = ptr[1];         /* a = 10 */
  1629.    Intro to DDS MICRO-C                                             Page: 32
  1630.  
  1631.  
  1632.    5. CONTROL STATEMENTS
  1633.    
  1634.          There are a number of statements in 'C', which  serve  to  control
  1635.       the flow of program execution.
  1636.    
  1637.       5.1 The IF statement
  1638.    
  1639.             The IF statement controls the execution of one other statement,
  1640.          based of  the  logical  value  (TRUE  or  FALSE)  of  a  CONDITION
  1641.          EXPRESSION:
  1642.    
  1643.            if(condition)
  1644.                statement;
  1645.    
  1646.             The "statement" in the above example would only be executed  if
  1647.          "condition" evaluated to a logically TRUE (non zero) value.
  1648.    
  1649.             An optional "else" clause may be added to the IF statement.  In
  1650.          this example, "statement-1" is executed if  "condition"  evaluates
  1651.          to TRUE, and "statement-2" is executed if "condition" evaluates to
  1652.          FALSE.
  1653.    
  1654.            if(condition)
  1655.                statement-1;
  1656.            else
  1657.                statement-2;
  1658.    
  1659.       5.2 The WHILE Loop
  1660.    
  1661.             The WHILE  statement  is  similar  to  the  first  form  of  IF
  1662.          statement (without  an  else),  except  that  the  "statement"  is
  1663.          repeated until the condition becomes  FALSE.  If  the  "statement"
  1664.          does not effect the condition, the statement will be executed over
  1665.          and over forever (ie: infinite loop).
  1666.    
  1667.            while(condition)
  1668.                statement;
  1669.    
  1670.             Try entering, compiling and executing the following program:
  1671.    
  1672.            #include stdio.h
  1673.            /* Our old familiar "count to 10" program, with a few
  1674.               improvements to let us see the numbers */
  1675.            main()
  1676.            {
  1677.                int a;
  1678.    
  1679.                a = 0;
  1680.                while(a < 10)
  1681.                    printf("A=%d\n", a++);
  1682.            }
  1683.    Intro to DDS MICRO-C                                             Page: 33
  1684.  
  1685.  
  1686.             Note the '\n' at the end of the prompt in the call to "printf".
  1687.          'C' operates on a concept called STREAM I/O, which means that  all
  1688.          input and  output  is  considered  to  occur  in  a  never  ending
  1689.          "stream", like a stream of water. There  are  no  "lines"  in  the
  1690.          stream unless we cause them. The '\n' sequence at the end  of  the
  1691.          prompt is a NEWLINE character, which tells the compiler to  insert
  1692.          the necessary code into the string to cause the output to go to  a
  1693.          NEW LINE on a terminal or printer when the  string  is  displayed.
  1694.          Try removing the '\n' from the prompt and see what happens.
  1695.    
  1696.       5.3 The DO/WHILE Loop
  1697.    
  1698.             The DO/WHILE statement  is  similar  to  the  WHILE  statement,
  1699.          except that  the  condition  is  tested  AFTER  the  statement  is
  1700.          executed, not BEFORE. Note  that  when  using  DO/WHILE,  you  are
  1701.          guarenteed that the statement will always  be  executed  at  least
  1702.          ONCE.
  1703.    
  1704.            do
  1705.                statement;
  1706.            while(conditon);
  1707.    
  1708.             Here is another example of our "count" program, which uses  our
  1709.          own function to output the number in decimal:
  1710.    
  1711.            #include stdio.h
  1712.    
  1713.            /* Main "count" program */
  1714.            main()
  1715.            {
  1716.                int a;
  1717.    
  1718.                a = 0;
  1719.                do
  1720.                    outnum(a);
  1721.                while(++a < 10);
  1722.            }
  1723.    
  1724.            /* Function to output a number in decimal */
  1725.            outnum(value)
  1726.                unsigned value;
  1727.            {
  1728.                char stack[6];      /* Small stack to hold digits */
  1729.                unsigned sp;        /* Our own stack pointer */
  1730.    
  1731.            /* calculate each digit of the number (in reverse order) */
  1732.                sp = 0;
  1733.                do
  1734.                    stack[sp++] = (value % 10) + '0';
  1735.                while(value /= 10);
  1736.            /* Display the stack of calculated digits */
  1737.                while(sp)
  1738.                    putc(stack[--sp], stdout);
  1739.                putc('\n', stdout);     /* move to new line */
  1740.            }
  1741.    Intro to DDS MICRO-C                                             Page: 34
  1742.  
  1743.  
  1744.             The "putc" function  is  another  function  from  the  STANDARD
  1745.          LIBRARY. The name "stdout" is defined in the "stdio.h"  file,  and
  1746.          tells "putc" that the character should  be  written  to  "standard
  1747.          output" (The PC console).
  1748.    
  1749.             The DO/WHILE loop in the "outnum" function demonstrates a  case
  1750.          where a simple  WHILE  would  not  suffice.  Try  to  re-code  the
  1751.          function using only WHILE loops. You might try:
  1752.    
  1753.            sp = 0;
  1754.            while(value)
  1755.                stack[sp++] = (value % 10) + '0', value /= 10;
  1756.    
  1757.          This appears to work, however, try executing "outnum(0)". The loop
  1758.          is never executed,  "sp"  is  never  incremented  from  zero,  and
  1759.          NOTHING is output. Not even a single '0'.
  1760.    
  1761.       5.4 The FOR Loop
  1762.    
  1763.             Notice that in the example above, we have to  initialize  "sp",
  1764.          test "value", and perform an operation on value at the end of  the
  1765.          loop. 'C' provides a special loop construct, just for  doing  such
  1766.          operations. It is called a FOR loop:
  1767.    
  1768.            for(initialization; condition; operation)
  1769.                statement;
  1770.    
  1771.             Using the FOR loop, we can rewrite the above example as:
  1772.    
  1773.            for(sp = 0; value; value /= 10)
  1774.                stack[sp++] = (value % 10) + '0';
  1775.    
  1776.             Actually, the FOR loop is more often used to  implement  simple
  1777.          loops which execute a predetermined number of times:
  1778.    
  1779.            /* A count loop, which executes 10 times */
  1780.            for(a=0; a < 10; ++a)
  1781.                printf("A=%d\n", a);
  1782.    
  1783.             Sometimes, it is possible to do all the computations  that  are
  1784.          required in  the  "initialization",  "condition"  and  "operation"
  1785.          expressions to the FOR loop. In  this  case,  you  could  use  the
  1786.          SEMICOLON ';' as the entire "statement" to tell FOR that  and  you
  1787.          don't want it to perform any other operations:
  1788.    
  1789.            for(a=0; a < 10; printf("A=%d\n", a++))
  1790.                ;       /* This is a NULL statement */
  1791.    Intro to DDS MICRO-C                                             Page: 35
  1792.  
  1793.  
  1794.             This semicolon by itself is called a NULL statement, and can be
  1795.          used anywhere that any other statement would be used.
  1796.    
  1797.            a = 0;
  1798.            while(a++ < 100)
  1799.                ;
  1800.    
  1801.            if(a == b)
  1802.                ;
  1803.            else
  1804.                printf("a is not equal to b");
  1805.    
  1806.             Note that the expressions in a FOR statement end with ';'. This
  1807.          means that they are also optional, and could be replaced  by  NULL
  1808.          statements.
  1809.    
  1810.            for(; a < 10; ++a) ;    /* No initialization */
  1811.            for(a = 0;; ++a) ;      /* No condition (infinite loop) */
  1812.            for(a = 0; ++a < 10;) ; /* No operation at end of loop */
  1813.            for(;;) ;               /* Standard way to do infinite loop */
  1814.    
  1815.       5.5 Compound Statements
  1816.    
  1817.             This is all well and good you say, but IF, WHILE, DO/WHILE  and
  1818.          FOR seem quite limited in that the "condition" or  "loop"  applies
  1819.          only to a single statement. What if I want to perform more complex
  1820.          calculations in my loop?
  1821.    
  1822.             Another very powerful feature of the 'C' language, is that  any
  1823.          number of ordinary statements may be placed together  in  a  group
  1824.          and treated as a single large statement. All you have to do is  to
  1825.          enclose them in CURLY BRACKETS '{ }'. For example:
  1826.    
  1827.            if(a == 10) {       /* '{' begins compound statement */
  1828.                printf("A was equal to 10... ");
  1829.                a = 99;
  1830.                printf("But its not anymore"); }    /* '}' ends */
  1831.            else
  1832.                printf("A was never equal to 10");
  1833.    
  1834.             You have already seen an example of compound statements, in the
  1835.          curly brackets which surround the body of functions.  Technically,
  1836.          each function consists of only one statement, but thanks  to  'C's
  1837.          compounding capability, you can actually use as many statements as
  1838.          you wish.
  1839.    Intro to DDS MICRO-C                                             Page: 36
  1840.  
  1841.  
  1842.       5.6 BREAK and CONTINUE
  1843.    
  1844.             Two more  'C'  statements  are  available  which  are  designed
  1845.          specially for extending the capabilities of loops.
  1846.    
  1847.             The BREAK statement causes the program to  skip  any  remaining
  1848.          statements in the loop, and to break out of  the  loop.  Execution
  1849.          will proceed with the first statement which follows the loop, just
  1850.          as if the loop had terminated in its normal fashion:
  1851.    
  1852.            for(a=0; a < 10; ++a) {
  1853.                if(a == 5)
  1854.                    break;
  1855.                printf("A=%d\n", a); }
  1856.    
  1857.             The above loop will never  reach  its  terminal  count  of  10,
  1858.          because the "break" statement will be executed  when  'a'  reaches
  1859.          five. Thus, the BREAK statement allows you to sprinkle  additional
  1860.          exit conditions throughout the body of the loop.
  1861.    
  1862.             The CONTINUE statement causes the loop to  skip  any  remaining
  1863.          statements in the loop, but to continue  looping.  Execution  will
  1864.          proceed as  if  all  the  statements  in  the  loop  had  executed
  1865.          normally:
  1866.    
  1867.            for(a=0; a < 10; ++a) {
  1868.                if(a != 5)
  1869.                    continue;
  1870.                printf("A=%d\n", a); }
  1871.    
  1872.             The above example will execute all 10 interations of the  loop,
  1873.          but the "printf" statement will only be executed for the  loop  in
  1874.          which 'a' is equal to 5.
  1875.    
  1876.       5.7 The SWITCH Statement
  1877.    
  1878.             Sometimes, you have a large number of conditions, which are  to
  1879.          be executed depending on the value of a certain variable. One  way
  1880.          that you could do this is with a series of "IF" statements,  using
  1881.          a popular "else if" construct:
  1882.    
  1883.            if(a == 1)
  1884.                statement-1;        /* Executed if a == 1 */
  1885.            else if(a == 2)
  1886.                statement-2;        /* Executed if a == 2 */
  1887.            else if(a == 3)
  1888.                statement-3;        /* Executed if a == 3 */
  1889.            else if(a == 4) {       /* Note compound statement */
  1890.                statement-4;        /* Executed if a == 4 */
  1891.                statement-5; }      /* Executed if a == 4 */
  1892.            else
  1893.                statement-6;        /* Executed if a == anything else */
  1894.    Intro to DDS MICRO-C                                             Page: 37
  1895.  
  1896.  
  1897.             'C' has  a  built  in  statement  to  implement  this  kind  of
  1898.          structure.  It  is  more  readable,  and  usually  generates  more
  1899.          efficent code than such a series of "IF" statements. It is  called
  1900.          a SWITCH statement:
  1901.    
  1902.            switch(a) {
  1903.                case 1 :
  1904.                    statement-1;        /* Executed if a == 1 */
  1905.                    break;
  1906.                case 2 ;
  1907.                    statement-2;        /* Executed if a == 2 */
  1908.                    break;
  1909.                case 3 :
  1910.                    statement-3;        /* Executed if a == 3 */
  1911.                    break;
  1912.                case 4 :
  1913.                    statement-4;        /* Executed if a == 4 */
  1914.                    statement-5;        /* Executed if a == 4 */
  1915.                    break;
  1916.                default:
  1917.                    statement-6; }      /* Executed of a == anything else */
  1918.    
  1919.             The "BREAK" statement at the  end  of  every  CASE  causes  the
  1920.          program to proceed to the statement immediately following the  end
  1921.          of the entire switch  construct.  If  it  were  not  present,  the
  1922.          statements in  a  case  would  "fall  through",  and  execute  the
  1923.          statements in the following case as well. Since the case values do
  1924.          not have to be presented in any particular  order,  this  behavior
  1925.          can often be used to your advantage by careful placing of the case
  1926.          statements relative to each other. Note also that the code in  the
  1927.          last case ("Default") does not need a "break" since it is  already
  1928.          at the end of the switch construct.
  1929.    
  1930.       5.8 Labels and GOTO
  1931.    
  1932.             If none of the above constructs does exactly what you  need  to
  1933.          structure a particular program. 'C' also  has  available  the  old
  1934.          familiar GOTO command. Although the use of "GOTO" is often frowned
  1935.          upon, it can save you much programming effort in  some  cases.  In
  1936.          order to use goto, you must have a LABEL.  Any  statement  may  be
  1937.          labeled by preceeding it with a name, followed immediatly by  ':'.
  1938.          For example:
  1939.    
  1940.            #include stdio.h
  1941.            /* Our "count to 10" program using goto looping */
  1942.            main()
  1943.            {
  1944.                int a;
  1945.    
  1946.                a = 0;
  1947.            count: printf("A=%d\n", a);     /* Labeled "count" */
  1948.                if(++a < 10)
  1949.                    goto count;
  1950.            }
  1951.    Intro to DDS MICRO-C                                             Page: 38
  1952.  
  1953.  
  1954.    6. RECURSION
  1955.    
  1956.          RECURSION is the ability of a function to call itself,  and  is  a
  1957.       powerful capability of the 'C' language.
  1958.    
  1959.          In a previous section, I explained how memory is allocated on  the
  1960.       stack to a function  when  it  begins  execution.  This  allows  each
  1961.       function to have its own local variables. It also  means  that  if  a
  1962.       function calls itself (by referencing its own name in  an  expression
  1963.       contained within it), the function will begin executing with its  own
  1964.       local memory, which is distinct from the local memory of the  calling
  1965.       function (which  is  itself!).  This  means  that  when  the  "lower"
  1966.       instance of the function terminates, it will not  have  affected  the
  1967.       memory or execution state of the "higher" version of the function.
  1968.    
  1969.          The classic example of a recursive  algorithm  is  the  FACTORIAL,
  1970.       which may be defined as: factorial(n) is equal  the  product  of  all
  1971.       numbers from one to n.
  1972.    
  1973.          Thus:
  1974.                    factorial(1) == 1       /* 1         */
  1975.                    factorial(2) == 2       /* 1*2       */
  1976.                    factorial(3) == 6       /* 1*2*3     */
  1977.                    factorial(4) == 24      /* 1*2*3*4   */
  1978.                    factorial(5) == 120     /* 1*2*3*4*5 */
  1979.    
  1980.          Using this algorithm, we can define an  ITERATIVE  (non-recursive)
  1981.       function to calculate the factorial of a passed value:
  1982.    
  1983.                /*
  1984.                 * ITERATIVE factorial function
  1985.                 */
  1986.                unsigned factorial(value)
  1987.                    unsigned value;
  1988.                {
  1989.                    unsigned result;
  1990.    
  1991.                    result = 1;             /* Begin with one */
  1992.                    while(value > 1)        /* For each value */
  1993.                        result *= value--;  /* Include in product & reduce */
  1994.    
  1995.                    return result;          /* Send back result */
  1996.                }
  1997.    
  1998.          You can see that in this above example, the function simply  loops
  1999.       the required number of times to perform  the  appropriate  number  of
  2000.       multiply operations to calculate the factorial. (The factorial  of  0
  2001.       is defined as 1, NOT 0, so the above function will return the correct
  2002.       result in this case).
  2003.    Intro to DDS MICRO-C                                             Page: 39
  2004.  
  2005.  
  2006.          Another way to define factorial is: factorial(n) = the product  of
  2007.       n and factorial(n-1). (Remember that the factorial of zero is defined
  2008.       as 1).
  2009.    
  2010.          Thus:
  2011.                    factorial(1) == 1       /* 1*1  */
  2012.                    factorial(2) == 2       /* 2*1  */
  2013.                    factorial(3) == 6       /* 3*2  */
  2014.                    factorial(4) == 24      /* 4*6  */
  2015.                    factorial(5) == 120     /* 5*24 */
  2016.    
  2017.          Using this algorithim, we  can  define  a  RECURSIVE  function  to
  2018.       calculate the factorial of a passed value:
  2019.    
  2020.                /*
  2021.                 * RECURSIVE factorial function
  2022.                 */
  2023.                unsigned factorial(value)
  2024.                    unsigned value;
  2025.                {
  2026.                    if(value == 0)  /* Factorial 0 is 1 */
  2027.                        return 1;
  2028.    
  2029.                    return value * factorial(value - 1);
  2030.                }
  2031.    
  2032.          In this example, you can see that the function will  call  itself,
  2033.       each  time  passing  a  reduced  value  until  a  value  of  zero  is
  2034.       encountered. When the zero value is passed, "factorial"  returns  the
  2035.       pre-defined result of one, and  all  other  called  versions  of  the
  2036.       function will perform a  single  multiplication,  and  pass  the  new
  2037.       result on. The value returned by the "highest" version of "factorial"
  2038.       will be the factorial of the originally passed value.
  2039.    
  2040.          This is the "classic" example of recursion, and it is a poor  one.
  2041.       Although it demonstrates the concept,  it  does  not  show  a  useful
  2042.       application. In fact, the recursive factorial function  will  execute
  2043.       slower and require much more memory  than  the  interative  function.
  2044.       (Remember each "version" of the function gets its own local memory).
  2045.    
  2046.          The MICRO-C compiler  itself  relies  heavily  on  recursion,  and
  2047.       provides much better examples of this programming technique since  it
  2048.       is used to accomplish feats which are not  easily  possible  using  a
  2049.       non-recursive algorithm.
  2050.    
  2051.          One such use of recursion in the compiler is  to  accomplish  'C's
  2052.       COMPOUND STATEMENT capability. Recall that multiple statements in 'C'
  2053.       may be  grouped  together  and  treated  as  a  single  statement  by
  2054.       enclosing them in CURLY BRACKETS  '{}'.  Any  statement  within  this
  2055.       "group" may also be a  compound  statement,  and  this  "nesting"  of
  2056.       compound statement blocks may continue to ANY LEVEL.
  2057.    Intro to DDS MICRO-C                                             Page: 40
  2058.  
  2059.  
  2060.          The compiler contains a  function  called  "statement",  which  is
  2061.       passed the first token from  a  'C'  statement,  and  processes  that
  2062.       statement.  This  function  contains  a  "switch"   statement   which
  2063.       processes the token, and decides the action to be performed for  that
  2064.       statement.  Note:  "tokens"  are  numeric  representations   of   the
  2065.       individual entities which may occur  in  the  source  file  (such  as
  2066.       keywords, symbol names, operators etc.).
  2067.    
  2068.          The "statement" function contains a  fragment  of  code  which  is
  2069.       similar to this:
  2070.    
  2071.                /*
  2072.                 * Evaluate a language statement
  2073.                 */
  2074.                statement(token)
  2075.                    unsigned token;
  2076.                {
  2077.                    /* ... Not shown ... */
  2078.                    switch(token) {     /* act upon the token */
  2079.                        case OCB:       /* '{' - begin a block */
  2080.                            while((token = get_token()) != CCB)
  2081.                                statement(token);
  2082.                            break;
  2083.                        case WHILE:
  2084.                            /* ... Not shown ... */
  2085.                            eval(CRB);
  2086.                            cond_jump(FALSE, b, -1);
  2087.                            statement(get_token());
  2088.                            test_jump(a);
  2089.                            /* ... Not shown ... */
  2090.                            break;
  2091.                        /* Other cases ... Not shown ... */ }
  2092.                }
  2093.    
  2094.          In  this  function,  a  "while"  keyword  causes   the   following
  2095.       expression to be evaluated, followed by  a  conditional  jump,  after
  2096.       which  a  single  statement  is  compiled  (by  recursive   call   to
  2097.       "statement"), followed by  a  jump  back  to  the  beginning  of  the
  2098.       expression evaluation.
  2099.    
  2100.          If "statement" finds an  Opening  Curly  Bracket  (OCB),  it  will
  2101.       accept and compile more statements (recursivly) until a Closing Curly
  2102.       Bracket (CCB) is found. Therefore, if the statement compiled  in  the
  2103.       "while" loop  begins  with  OCB,  that  version  of  the  "statement"
  2104.       function will compile all subsequent statements up to CCB. When  that
  2105.       version of  "statement"  terminates,  the  original  version  of  the
  2106.       function (handling the "while") will then compile the  closing  jump.
  2107.       This has the effect that all statements between OCB and CCB ('{'  and
  2108.       '}') will be included in the body of the "while" loop.
  2109.    
  2110.          Another case where recursion is used within the MICRO-C  compiler,
  2111.       is to evaluate sub-expressions (contained  in  round  brackets  '()')
  2112.       which are inside another expression. In  this  case,  the  expression
  2113.       evaluation function calls itself (recursivly) when an  Opening  Round
  2114.       Bracket (ORB) is encountered.
  2115.    Intro to DDS MICRO-C                                             Page: 41
  2116.  
  2117.  
  2118.    7. COMMAND LINE ARGUMENTS
  2119.    
  2120.          When a 'C' program is invoked  by  typing  its  name  at  the  DOS
  2121.       command prompt, the remainder of the command line is broken down into
  2122.       distinct "words" (based on separating spaces or tabs), and passed  as
  2123.       standard 'C' arguments to the main function.
  2124.    
  2125.          Two values are passed to "main", the first is an integer count  of
  2126.       the number of command line arguments which were found, and the second
  2127.       is an array of pointers to character strings which  contain  each  of
  2128.       the arguments. In order that the program  may  identify  itself,  the
  2129.       first (zero'th) argument is always the name of  the  file  containing
  2130.       the programs executable image.
  2131.    
  2132.          For example, consider this program, compiled and saved in  a  file
  2133.       called "TEST.COM":
  2134.    
  2135.            #include stdio.h        /* Standard I/O definitions */
  2136.    
  2137.            /*
  2138.             * Command line arguments - DEMO program
  2139.             */
  2140.            main(argc, argv)
  2141.                int argc;       /* Count of arguments */
  2142.                char *argv[]    /* Array of pointers to char strings */
  2143.            {
  2144.                int i;          /* Temporary counter variable */
  2145.    
  2146.                for(i=0; i < argc; ++i)
  2147.                    printf("argv[%d] = '%s'\n", i, argv[i]);
  2148.            }
  2149.    
  2150.          When executed with the following command line:
  2151.    
  2152.                            TEST the quick brown fox
  2153.    
  2154.          The program will display the following output:
  2155.    
  2156.            argv[0] = 'TEST.COM'
  2157.            argv[1] = 'the'
  2158.            argv[2] = 'quick'
  2159.            argv[3] = 'brown'
  2160.            argv[4] = 'fox'
  2161.    
  2162.          NOTE1: The 'argc' value includes argv[0]  (program  name)  in  its
  2163.       argument count.
  2164.    
  2165.          NOTE2: Like any other  'C'  function,  "main"  does  not  have  to
  2166.       declare its arguments unless it is going to use them.
  2167.    Intro to DDS MICRO-C                                             Page: 42
  2168.  
  2169.  
  2170.    8. FILE ACCESS
  2171.    
  2172.          As mentioned before, all I/O  in  'C'  is  performed  by  STANDARD
  2173.       LIBRARY FUNCTIONS. Before any  file  access  can  be  performed,  the
  2174.       header file "stdio.h" must be included in the  source  (Via  #include
  2175.       pre-processor directive), in order to  properly  define  the  various
  2176.       functions and types which are used on your particular system.
  2177.    
  2178.          For  detailed  information  on  the  standard  library   functions
  2179.       mentioned below, see the MICRO-C technical manual.  NOTE  that  cross
  2180.       compilers for embedded systems (or any other environment  which  does
  2181.       not have an general "operating system") do not usually  provide  file
  2182.       I/O functions. Refer to the library documentation for your compiler.
  2183.    
  2184.       8.1 File Pointers
  2185.    
  2186.             All files in 'C' are identified by a FILE POINTER, which  is  a
  2187.          value returned by the operating system when the  file  is  OPENED.
  2188.          Since the type of value used to identify files may vary  from  one
  2189.          operating system to another, the "stdio.h" header file  defines  a
  2190.          data type called "FILE" which contains the correct definition  for
  2191.          your particular operating system. This allows the  declaration  of
  2192.          the file pointers to  be  portable  from  one  system  to  another
  2193.          without changing the program source code.
  2194.    
  2195.       8.2 File I/O Functions
  2196.    
  2197.             The standard library function "fopen" is used to open a file by
  2198.          name, and obtain the file pointer value.
  2199.    
  2200.             The functions "getc", "fread", "fgets" and "fscanf" may be used
  2201.          to read information from an open file.
  2202.    
  2203.             The functions "putc", "fwrite", "fputs" and  "fprintf"  may  be
  2204.          used to write information to an open file.
  2205.    
  2206.             The function "fclose" is used to close the file, which  informs
  2207.          the operating system that you are finished with it.
  2208.    Intro to DDS MICRO-C                                             Page: 43
  2209.  
  2210.  
  2211.                /*
  2212.                 * Sample program to copy a file called "input"
  2213.                 * To a file called "output". Note: To keep this
  2214.                 * example simple, no error checking is perormed.
  2215.                 */
  2216.                main()
  2217.                {
  2218.                    char buffer[1000];  /* Declare a copy buffer */
  2219.                    int nbytes;         /* Records # bytes read */
  2220.                    FILE *ifp, *ofp     /* Declare file pointers */
  2221.    
  2222.                /* Open the files */
  2223.                    ifp = fopen("input","r");   /* Open for Read access */
  2224.                    ofp = fopen("output", "w"); /* Open for Write access */
  2225.    
  2226.                /* Copy data in 1000 byte blocks */
  2227.                    do {
  2228.                        nbytes = fread(buffer, 1000, fp);   /* Read data */
  2229.                        fwrite(buffer, nbytes, fp); }       /* Write data */
  2230.                    while(nbytes == 1000);
  2231.    
  2232.                    fclose(ifp);            /* Close the input file */
  2233.                    fclose(ofp);            /* Close the output file */
  2234.                }
  2235.    
  2236.       8.3 Standard I/O
  2237.    
  2238.             Whenever a 'C' program is executed,  three  file  pointers  are
  2239.          automatically  established  which  allow  access  to  the  console
  2240.          keyboard and display:
  2241.    
  2242.            stdin   - Reads input from the console keyboard. Note that stdin
  2243.                      may be REDIRECTED (using '<filename'). For example:
  2244.                               program <input.dat
  2245.                      executes "program", and causes it to read its standard
  2246.                      input from "input.dat" instead of the keyboard.
  2247.    
  2248.            stdout  - Writes to the console display. Note that stdout may be
  2249.                      REDIRECTED (using '>filename). For example:
  2250.                              program >output.dat
  2251.                      executes "program", and causes  it to  write  standard
  2252.                      output to "output.dat" instead of the display.
  2253.    
  2254.            stderr  - Also writes to  the  console display,  but  CANNOT  BE
  2255.                      REDIRECTED, usually used to insure that error messages
  2256.                      will be displayed on the console even  if  the  output
  2257.                      has been redirected.
  2258.    
  2259.             The stdin, stdout and stderr file pointers are defined  in  the
  2260.          "stdio.h" header file, and are always available. They do not  have
  2261.          to be opened or closed.
  2262.    
  2263.             Since "stdin" and "stdout"  are  used  very  often  within  'C'
  2264.          programs, the functions "scanf" and "printf" are available.  These
  2265.          behave exactly the same as  the  general  "fscanf"  and  "fprintf"
  2266.          functions, except that they do not accept a file pointer argument,
  2267.          and always access stdin and stdout.
  2268.    Intro to DDS MICRO-C                                             Page: 44
  2269.  
  2270.  
  2271.    9. SAMPLE FUNCTIONS
  2272.    
  2273.          Here are some sample 'C' functions, demonstrating features of  'C'
  2274.       which we have discussed:
  2275.    
  2276.          Any function used in an example  but  not  defined  therein  is  a
  2277.       Library Function.  Refer  to  the  MICRO-C  Technical  Manual  for  a
  2278.       description.
  2279.    
  2280.       9.1 Prime Number Generator
  2281.    
  2282.            #include stdio.h        /* Standard I/O definitions */
  2283.    
  2284.            /*
  2285.             * This program tests a range of numbers, and prints out any
  2286.             * values which it finds to be prime. Each value is divided
  2287.             * by increasing values from 2 to (num/2). The "modulus" ('%')
  2288.             * operator is used, resulting in a zero result (no remainder)
  2289.             * if a factor is found. The main loop is incremented by two,
  2290.             * to skip even numbers which are never prime (except for 2
  2291.             * which is not shown by this program).
  2292.             */
  2293.            main()
  2294.            {
  2295.                int num, test, limit;
  2296.                char flag;
  2297.    
  2298.                for(num=1; num < 1000; num += 2) {      /* Test range */
  2299.                    limit = num/2;                      /* Only test to 1/2 */
  2300.                    flag = 1;                           /* Assume prime */
  2301.                    for(test = 2; test < limit; ++test) { /* Test factors */
  2302.                        if(!(num%test)) {               /* No remain: factor */
  2303.                            flag = 0;                   /* Not prime */
  2304.                            break; } }                  /* Waste no more time */ 
  2305.                    if(flag)                            /* Prime, display */
  2306.                        printf("%d\n", num); }
  2307.            }
  2308.    Intro to DDS MICRO-C                                             Page: 45
  2309.  
  2310.  
  2311.       9.2 A Simple Sort
  2312.    
  2313.            #include stdio.h        /* Standard I/O definitions */
  2314.    
  2315.            /*
  2316.             * This is an array of unsorted numbers
  2317.             */
  2318.            int numbers[10] = { 13, 25, 22, 7, 16, 91, 11, 41, 18, 0 };
  2319.    
  2320.            /*
  2321.             * This main program calls a function "sort" which re-arranges
  2322.             * the elements of an integer array to place them in ascending
  2323.             * order. It then prints out the resultant array using a simple
  2324.             * loop.
  2325.             */
  2326.            main()
  2327.            {
  2328.                int i;
  2329.    
  2330.                sort(numbers, 10);      /* Perform the sort */
  2331.    
  2332.                for(i=0; i < 10; ++i)   /* Display contents of array */
  2333.                    printf("[%d]=%d\n", i, numbers[i]);
  2334.            }
  2335.    
  2336.            /*
  2337.             * Function to sort an array of numbers. It is passed the
  2338.             * address of an integer array, and the size (in elements).
  2339.             *
  2340.             * Note: The declaration 'int array[]' identifies "array" as a
  2341.             * single dimension integer array of unspecified size. Since
  2342.             * arrays in 'C' are passed as a pointer value to the array
  2343.             * address, accesses to "array" will access the actual contents
  2344.             * of the passed array variable, allowing that variable to be
  2345.             * modified directly by this function.
  2346.             */
  2347.            sort(array, size)
  2348.                int array[], size;
  2349.            {
  2350.                int i, j, lowest;
  2351.    
  2352.                for(i=0; i < size; ++i) {           /* For each element */
  2353.                    lowest = i;
  2354.                    for(j=i+1; j < size; ++j)       /* Search higher elems */
  2355.                        if(array[j] < array[lowest])
  2356.                            lowest = j;             /* And remember lowest */
  2357.                    j = array[lowest];              /* Swap with original */
  2358.                    array[lowest] = array[i];
  2359.                    array[i] = j; }
  2360.            }
  2361.    Intro to DDS MICRO-C                                             Page: 46
  2362.  
  2363.  
  2364.       9.3 Text Display of Value
  2365.    
  2366.             This program accepts any  number  of  command  line  arguments,
  2367.          which it evaluates as unsigned numbers, and  displays  the  result
  2368.          for each argument using english text.
  2369.    
  2370.             For example, if this  program  were  saved  in  a  file  called
  2371.          "TEXTNUM.COM", and the following command is executed:
  2372.    
  2373.                TEXTNUM 1000 1100 1111 31415 9265 358
  2374.    
  2375.             The program will display the following output:
  2376.    
  2377.                One Thousand
  2378.                One Thousand, One Hundred
  2379.                One Thousand, One Hundred and Eleven
  2380.                Thirty One Thousand, Four Hundred and Fifteen
  2381.                Nine Thousand, Two Hundred and Sixty Five
  2382.                Three Hundred and Fifty Eight
  2383.    
  2384.             Here is a listing of the program:
  2385.    
  2386.            #include stdio.h
  2387.    
  2388.            /*
  2389.             * Main program which processes all of its arguments,
  2390.             * interpreting each one as a numeric value, and
  2391.             * displaying that value as english text.
  2392.             */
  2393.            main(argc, argv)
  2394.                int argc;
  2395.                char *argv[];
  2396.            {
  2397.                int i;
  2398.    
  2399.                if(argc < 2)                /* No arguments given */
  2400.                    abort("\nUse: textnum <value> ...\n");
  2401.    
  2402.                for(i=1; i < argc; ++i) {   /* Display all arguments */
  2403.                    textnum(atoi(argv[i]));
  2404.                    putc('\n', stdout); }
  2405.            }
  2406.    
  2407.            /* >>> Continued on Next Page >>> */
  2408.    Intro to DDS MICRO-C                                             Page: 47
  2409.  
  2410.  
  2411.            /*
  2412.             * Text tables and associated function to display an
  2413.             * unsigned integer value as a string of words.
  2414.             * Note the use of RECURSION to display the number
  2415.             * of thousands and hundreds.
  2416.             */
  2417.    
  2418.            /* Table of single digits and teens */
  2419.            char *digits[] = {
  2420.                "Zero", "One", "Two", "Three", "Four", "Five", "Six",
  2421.                "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve",
  2422.                "Thirteen", "Fourteen", "Fifteen", "Sixteen",
  2423.                "Seventeen", "Eighteen", "Nineteen" };
  2424.    
  2425.            /* Table of tens prefix's */
  2426.            char *tens[] = {
  2427.                "Ten", "Twenty", "Thirty", "Fourty", "Fifty",
  2428.                "Sixty", "Seventy", "Eighty", "Ninety" };
  2429.    
  2430.            /* Function to display number as string */
  2431.            textnum(value)
  2432.                unsigned value;
  2433.            {
  2434.                char join_flag;
  2435.    
  2436.                join_flag = 0;
  2437.    
  2438.                if(value >= 1000) {             /* Display thousands */
  2439.                    textnum(value/1000);
  2440.                    fputs(" Thousand", stdout);
  2441.                    if(!(value %= 1000))
  2442.                        return;
  2443.                    join_flag = 1; }
  2444.    
  2445.                if(value >= 100) {              /* Display hundreds */
  2446.                    if(join_flag)
  2447.                        fputs(", ", stdout);
  2448.                    textnum(value/100);
  2449.                    fputs(" Hundred", stdout);
  2450.                    if(!(value %= 100))
  2451.                        return;
  2452.                    join_flag = 1; }
  2453.    
  2454.                if(join_flag)                   /* Separator if required */
  2455.                    fputs(" and ", stdout);
  2456.    
  2457.                if(value > 19) {                /* Display tens */
  2458.                    fputs(tens[(value/10)-1], stdout);
  2459.                    if(!(value %= 10))
  2460.                        return;
  2461.                    putc(' ', stdout); }
  2462.    
  2463.                fputs(digits[value], stdout);   /* Display digits */
  2464.            }
  2465.  
  2466.  
  2467.  
  2468.                              Intro to DDS MICRO-C
  2469.  
  2470.                               TABLE OF CONTENTS
  2471.  
  2472.  
  2473.                                                                         Page
  2474.  
  2475.     1. INTRODUCTION                                                        1
  2476.  
  2477.  
  2478.     2. BACKGROUND INFORMATION                                              2
  2479.  
  2480.        2.1 Computer Architecture                                           2
  2481.        2.2 Assembly Language                                               5
  2482.        2.3 High Level Languages                                            6
  2483.        2.4 Interpreters VS Compilers                                       8
  2484.        2.5 Object Modules & Linking                                        9
  2485.        2.6 Compiler Libraries                                             10
  2486.        2.7 Portability                                                    10
  2487.  
  2488.     3. INTRODUCTION TO 'C'                                                11
  2489.  
  2490.        3.1 Functions                                                      12
  2491.        3.2 Variables                                                      13
  2492.        3.3 Pointers                                                       16
  2493.        3.4 A complete 'C' program                                         16
  2494.        3.5 'C' memory organization                                        18
  2495.  
  2496.     4. EXPRESSIONS                                                        21
  2497.  
  2498.        4.1 Unary operators                                                22
  2499.        4.2 Binary Operators                                               24
  2500.        4.3 Other Operators                                                29
  2501.  
  2502.     5. CONTROL STATEMENTS                                                 32
  2503.  
  2504.        5.1 The IF statement                                               32
  2505.        5.2 The WHILE Loop                                                 32
  2506.        5.3 The DO/WHILE Loop                                              33
  2507.        5.4 The FOR Loop                                                   34
  2508.        5.5 Compound Statements                                            35
  2509.        5.6 BREAK and CONTINUE                                             36
  2510.        5.7 The SWITCH Statement                                           36
  2511.        5.8 Labels and GOTO                                                37
  2512.  
  2513.     6. RECURSION                                                          38
  2514.  
  2515.  
  2516.     7. COMMAND LINE ARGUMENTS                                             41
  2517.  
  2518.  
  2519.     8. FILE ACCESS                                                        42
  2520.  
  2521.        8.1 File Pointers                                                  42
  2522.  
  2523.    Intro to DDS MICRO-C                                   Table of Contents
  2524.  
  2525.                                                                         Page
  2526.        8.2 File I/O Functions                                             42
  2527.        8.3 Standard I/O                                                   43
  2528.  
  2529.     9. SAMPLE FUNCTIONS                                                   44
  2530.  
  2531.        9.1 Prime Number Generator                                         44
  2532.        9.2 A Simple Sort                                                  45
  2533.        9.3 Text Display of Value                                          46
  2534.